aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
authormeta72010-08-30 11:42:17 -0700
committermeta72010-08-30 11:42:17 -0700
commit35d6181b78525df995cf2dc5f8bb4f102f3c0aad (patch)
tree725b6fcda44f24f578cde7851aac869c59c0af82 /OpenSim/Region/Framework
parentKick the user from the region in the circumstance that the TP home failed - O... (diff)
parentMerge branch 'master' into careminster-presence-refactor (diff)
downloadopensim-SC_OLD-35d6181b78525df995cf2dc5f8bb4f102f3c0aad.zip
opensim-SC_OLD-35d6181b78525df995cf2dc5f8bb4f102f3c0aad.tar.gz
opensim-SC_OLD-35d6181b78525df995cf2dc5f8bb4f102f3c0aad.tar.bz2
opensim-SC_OLD-35d6181b78525df995cf2dc5f8bb4f102f3c0aad.tar.xz
Merge branch 'careminster-presence-refactor' of ssh://3dhosting.de/var/git/careminster into careminster-presence-refactor
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs12
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs189
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs98
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs205
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs152
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs16
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs68
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs143
15 files changed, 622 insertions, 341 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 9fe6d96..59c035f 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -136,5 +136,13 @@ namespace OpenSim.Region.Framework.Interfaces
136 /// A <see cref="IClientAPI"/> 136 /// A <see cref="IClientAPI"/>
137 /// </param> 137 /// </param>
138 void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient); 138 void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient);
139
140 /// <summary>
141 /// Update the position of an attachment
142 /// </summary>
143 /// <param name="client"></param>
144 /// <param name="sog"></param>
145 /// <param name="pos"></param>
146 void UpdateAttachmentPosition(IClientAPI client, SceneObjectGroup sog, Vector3 pos);
139 } 147 }
140} 148}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 1e2f60b..f5cd528 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -29,6 +29,7 @@ using System.Collections.Generic;
29using System.Collections; 29using System.Collections;
30using OpenMetaverse; 30using OpenMetaverse;
31using OpenSim.Framework; 31using OpenSim.Framework;
32using OpenSim.Region.Framework.Scenes;
32 33
33namespace OpenSim.Region.Framework.Interfaces 34namespace OpenSim.Region.Framework.Interfaces
34{ 35{
@@ -155,6 +156,17 @@ namespace OpenSim.Region.Framework.Interfaces
155 /// If no inventory item has that name then an empty list is returned. 156 /// If no inventory item has that name then an empty list is returned.
156 /// </returns> 157 /// </returns>
157 IList<TaskInventoryItem> GetInventoryItems(string name); 158 IList<TaskInventoryItem> GetInventoryItems(string name);
159
160 /// <summary>
161 /// Get the scene object referenced by an inventory item.
162 /// </summary>
163 ///
164 /// This is returned in a 'rez ready' state. That is, name, description, permissions and other details have
165 /// been adjusted to reflect the part and item from which it originates.
166 ///
167 /// <param name="item"></param>
168 /// <returns>The scene object. Null if the scene object asset couldn't be found</returns>
169 SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item);
158 170
159 /// <summary> 171 /// <summary>
160 /// Update an existing inventory item. 172 /// Update an existing inventory item.
diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index e093f0a..81e4952 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -28,6 +28,7 @@
28using System.Net; 28using System.Net;
29using OpenMetaverse; 29using OpenMetaverse;
30using OpenMetaverse.Packets; 30using OpenMetaverse.Packets;
31using OpenMetaverse.Messages.Linden;
31using OpenMetaverse.StructuredData; 32using OpenMetaverse.StructuredData;
32 33
33namespace OpenSim.Region.Framework.Interfaces 34namespace OpenSim.Region.Framework.Interfaces
@@ -54,7 +55,7 @@ namespace OpenSim.Region.Framework.Interfaces
54 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket); 55 uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket);
55 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat, 56 void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID toAgent, bool canVoiceChat,
56 bool isModerator, bool textMute); 57 bool isModerator, bool textMute);
57 void ParcelProperties(ParcelPropertiesPacket parcelPropertiesPacket, UUID avatarID); 58 void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID);
58 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID); 59 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID);
59 } 60 }
60} 61}
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 145f9ed..3a3ec2b 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -31,7 +31,7 @@ namespace OpenSim.Region.Framework.Scenes
31 31
32 public class Prioritizer 32 public class Prioritizer
33 { 33 {
34 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 34// private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
35 35
36 /// <summary> 36 /// <summary>
37 /// This is added to the priority of all child prims, to make sure that the root prim update is sent to the 37 /// This is added to the priority of all child prims, to make sure that the root prim update is sent to the
@@ -75,7 +75,6 @@ namespace OpenSim.Region.Framework.Scenes
75 break; 75 break;
76 default: 76 default:
77 throw new InvalidOperationException("UpdatePrioritizationScheme not defined."); 77 throw new InvalidOperationException("UpdatePrioritizationScheme not defined.");
78 break;
79 } 78 }
80 79
81 // Adjust priority so that root prims are sent to the viewer first. This is especially important for 80 // Adjust priority so that root prims are sent to the viewer first. This is especially important for
@@ -122,9 +121,16 @@ namespace OpenSim.Region.Framework.Scenes
122 // Use group position for child prims 121 // Use group position for child prims
123 Vector3 entityPos; 122 Vector3 entityPos;
124 if (entity is SceneObjectPart) 123 if (entity is SceneObjectPart)
125 entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition; 124 {
125 // Can't use Scene.GetGroupByPrim() here, since the entity may have been delete from the scene
126 // before its scheduled update was triggered
127 //entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
128 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
129 }
126 else 130 else
131 {
127 entityPos = entity.AbsolutePosition; 132 entityPos = entity.AbsolutePosition;
133 }
128 134
129 return Vector3.DistanceSquared(presencePos, entityPos); 135 return Vector3.DistanceSquared(presencePos, entityPos);
130 } 136 }
@@ -157,7 +163,9 @@ namespace OpenSim.Region.Framework.Scenes
157 } 163 }
158 } 164 }
159 else 165 else
166 {
160 entityPos = entity.AbsolutePosition; 167 entityPos = entity.AbsolutePosition;
168 }
161 169
162 if (!presence.IsChildAgent) 170 if (!presence.IsChildAgent)
163 { 171 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index ab18c93..8760c84 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -122,7 +122,7 @@ namespace OpenSim.Region.Framework.Scenes
122 else 122 else
123 { 123 {
124 m_log.WarnFormat( 124 m_log.WarnFormat(
125 "[AGENT INVENTORY]: Agent {1} could not add item {2} {3}", 125 "[AGENT INVENTORY]: Agent {0} could not add item {1} {2}",
126 AgentID, item.Name, item.ID); 126 AgentID, item.Name, item.ID);
127 127
128 return; 128 return;
@@ -984,7 +984,6 @@ namespace OpenSim.Region.Framework.Scenes
984 984
985 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) 985 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId)
986 { 986 {
987 Console.WriteLine("CreateAgentInventoryItemFromTask");
988 TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId); 987 TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId);
989 988
990 if (null == taskItem) 989 if (null == taskItem)
@@ -1055,7 +1054,10 @@ namespace OpenSim.Region.Framework.Scenes
1055 /// <param name="itemID"></param> 1054 /// <param name="itemID"></param>
1056 public InventoryItemBase MoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, SceneObjectPart part, UUID itemId) 1055 public InventoryItemBase MoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, SceneObjectPart part, UUID itemId)
1057 { 1056 {
1058 m_log.Info("Adding task inventory"); 1057 m_log.DebugFormat(
1058 "[PRIM INVENTORY]: Adding item {0} from {1} to folder {2} for {3}",
1059 itemId, part.Name, folderId, remoteClient.Name);
1060
1059 InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(remoteClient.AgentId, part, itemId); 1061 InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(remoteClient.AgentId, part, itemId);
1060 1062
1061 if (agentItem == null) 1063 if (agentItem == null)
@@ -1121,7 +1123,11 @@ namespace OpenSim.Region.Framework.Scenes
1121 /// <see>MoveTaskInventoryItem</see> 1123 /// <see>MoveTaskInventoryItem</see>
1122 /// </summary> 1124 /// </summary>
1123 /// <param name="remoteClient"></param> 1125 /// <param name="remoteClient"></param>
1124 /// <param name="folderID"></param> 1126 /// <param name="folderID">
1127 /// The user inventory folder to move (or copy) the item to. If null, then the most
1128 /// suitable system folder is used (e.g. the Objects folder for objects). If there is no suitable folder, then
1129 /// the item is placed in the user's root inventory folder
1130 /// </param>
1125 /// <param name="part"></param> 1131 /// <param name="part"></param>
1126 /// <param name="itemID"></param> 1132 /// <param name="itemID"></param>
1127 public InventoryItemBase MoveTaskInventoryItem(UUID avatarId, UUID folderId, SceneObjectPart part, UUID itemId) 1133 public InventoryItemBase MoveTaskInventoryItem(UUID avatarId, UUID folderId, SceneObjectPart part, UUID itemId)
@@ -1846,53 +1852,6 @@ namespace OpenSim.Region.Framework.Scenes
1846 } 1852 }
1847 } 1853 }
1848 1854
1849 public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID)
1850 {
1851 SceneObjectGroup objectGroup = grp;
1852 if (objectGroup != null)
1853 {
1854 if (!grp.HasGroupChanged)
1855 {
1856 m_log.InfoFormat("[ATTACHMENT]: Save request for {0} which is unchanged", grp.UUID);
1857 return;
1858 }
1859
1860 m_log.InfoFormat(
1861 "[ATTACHMENT]: Updating asset for attachment {0}, attachpoint {1}",
1862 grp.UUID, grp.GetAttachmentPoint());
1863
1864 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup);
1865
1866 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
1867 item = InventoryService.GetItem(item);
1868
1869 if (item != null)
1870 {
1871 AssetBase asset = CreateAsset(
1872 objectGroup.GetPartName(objectGroup.LocalId),
1873 objectGroup.GetPartDescription(objectGroup.LocalId),
1874 (sbyte)AssetType.Object,
1875 Utils.StringToBytes(sceneObjectXml),
1876 remoteClient.AgentId);
1877 AssetService.Store(asset);
1878
1879 item.AssetID = asset.FullID;
1880 item.Description = asset.Description;
1881 item.Name = asset.Name;
1882 item.AssetType = asset.Type;
1883 item.InvType = (int)InventoryType.Object;
1884
1885 InventoryService.UpdateItem(item);
1886
1887 // this gets called when the agent loggs off!
1888 if (remoteClient != null)
1889 {
1890 remoteClient.SendInventoryItemCreateUpdate(item, 0);
1891 }
1892 }
1893 }
1894 }
1895
1896 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID) 1855 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
1897 { 1856 {
1898 itemID = UUID.Zero; 1857 itemID = UUID.Zero;
@@ -1998,7 +1957,7 @@ namespace OpenSim.Region.Framework.Scenes
1998 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 1957 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
1999 RezSelected, RemoveItem, fromTaskID, false); 1958 RezSelected, RemoveItem, fromTaskID, false);
2000 } 1959 }
2001 1960
2002 /// <summary> 1961 /// <summary>
2003 /// Rez an object into the scene from a prim's inventory. 1962 /// Rez an object into the scene from a prim's inventory.
2004 /// </summary> 1963 /// </summary>
@@ -2013,95 +1972,32 @@ namespace OpenSim.Region.Framework.Scenes
2013 SceneObjectPart sourcePart, TaskInventoryItem item, 1972 SceneObjectPart sourcePart, TaskInventoryItem item,
2014 Vector3 pos, Quaternion rot, Vector3 vel, int param) 1973 Vector3 pos, Quaternion rot, Vector3 vel, int param)
2015 { 1974 {
2016 // Rez object 1975 if (null == item)
2017 if (item != null) 1976 return null;
2018 { 1977
2019 UUID ownerID = item.OwnerID; 1978 SceneObjectGroup group = sourcePart.Inventory.GetRezReadySceneObject(item);
2020 1979
2021 AssetBase rezAsset = AssetService.Get(item.AssetID.ToString()); 1980 if (null == group)
2022 1981 return null;
2023 if (rezAsset != null) 1982
2024 { 1983 if (!Permissions.CanRezObject(group.PrimCount, item.OwnerID, pos))
2025 string xmlData = Utils.BytesToString(rezAsset.Data); 1984 return null;
2026 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
2027
2028 if (!Permissions.CanRezObject(group.Children.Count, ownerID, pos))
2029 {
2030 return null;
2031 }
2032 group.ResetIDs();
2033
2034 AddNewSceneObject(group, true);
2035
2036 // we set it's position in world.
2037 group.AbsolutePosition = pos;
2038
2039 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
2040
2041 // Since renaming the item in the inventory does not affect the name stored
2042 // in the serialization, transfer the correct name from the inventory to the
2043 // object itself before we rez.
2044 rootPart.Name = item.Name;
2045 rootPart.Description = item.Description;
2046
2047 List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values);
2048
2049 group.SetGroup(sourcePart.GroupID, null);
2050
2051 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0)
2052 {
2053 if (Permissions.PropagatePermissions())
2054 {
2055 foreach (SceneObjectPart part in partList)
2056 {
2057 part.EveryoneMask = item.EveryonePermissions;
2058 part.NextOwnerMask = item.NextPermissions;
2059 }
2060 group.ApplyNextOwnerPermissions();
2061 }
2062 }
2063
2064 foreach (SceneObjectPart part in partList)
2065 {
2066 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0)
2067 {
2068 part.LastOwnerID = part.OwnerID;
2069 part.OwnerID = item.OwnerID;
2070 part.Inventory.ChangeInventoryOwner(item.OwnerID);
2071 }
2072 part.EveryoneMask = item.EveryonePermissions;
2073 part.NextOwnerMask = item.NextPermissions;
2074 }
2075
2076 rootPart.TrimPermissions();
2077
2078 if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
2079 {
2080 group.ClearPartAttachmentData();
2081 }
2082
2083 group.UpdateGroupRotationR(rot);
2084
2085 //group.ApplyPhysics(m_physicalPrim);
2086 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero)
2087 {
2088 group.RootPart.ApplyImpulse((vel * group.GetMass()), false);
2089 group.Velocity = vel;
2090 rootPart.ScheduleFullUpdate();
2091 }
2092 group.CreateScriptInstances(param, true, DefaultScriptEngine, 2);
2093 rootPart.ScheduleFullUpdate();
2094 1985
2095 if (!Permissions.BypassPermissions()) 1986 if (!Permissions.BypassPermissions())
2096 { 1987 {
2097 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) 1988 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
2098 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 1989 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
2099 }
2100 return rootPart.ParentGroup;
2101 }
2102 } 1990 }
2103 1991
2104 return null; 1992 AddNewSceneObject(group, true, pos, rot, vel);
1993
1994 // We can only call this after adding the scene object, since the scene object references the scene
1995 // to find out if scripts should be activated at all.
1996 group.CreateScriptInstances(param, true, DefaultScriptEngine, 2);
1997
1998 group.ScheduleGroupForFullUpdate();
1999
2000 return group;
2105 } 2001 }
2106 2002
2107 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, UUID AgentId) 2003 public virtual bool returnObjects(SceneObjectGroup[] returnobjects, UUID AgentId)
@@ -2161,7 +2057,11 @@ namespace OpenSim.Region.Framework.Scenes
2161 sog.SetGroup(groupID, remoteClient); 2057 sog.SetGroup(groupID, remoteClient);
2162 sog.ScheduleGroupForFullUpdate(); 2058 sog.ScheduleGroupForFullUpdate();
2163 2059
2164 foreach (SceneObjectPart child in sog.Children.Values) 2060 List<SceneObjectPart> partList = null;
2061 lock (sog.Children)
2062 partList = new List<SceneObjectPart>(sog.Children.Values);
2063
2064 foreach (SceneObjectPart child in partList)
2165 child.Inventory.ChangeInventoryOwner(ownerID); 2065 child.Inventory.ChangeInventoryOwner(ownerID);
2166 } 2066 }
2167 else 2067 else
@@ -2171,8 +2071,12 @@ namespace OpenSim.Region.Framework.Scenes
2171 2071
2172 if (sog.GroupID != groupID) 2072 if (sog.GroupID != groupID)
2173 continue; 2073 continue;
2074
2075 List<SceneObjectPart> partList = null;
2076 lock (sog.Children)
2077 partList = new List<SceneObjectPart>(sog.Children.Values);
2174 2078
2175 foreach (SceneObjectPart child in sog.Children.Values) 2079 foreach (SceneObjectPart child in partList)
2176 { 2080 {
2177 child.LastOwnerID = child.OwnerID; 2081 child.LastOwnerID = child.OwnerID;
2178 child.Inventory.ChangeInventoryOwner(groupID); 2082 child.Inventory.ChangeInventoryOwner(groupID);
@@ -2180,8 +2084,7 @@ namespace OpenSim.Region.Framework.Scenes
2180 2084
2181 sog.SetOwnerId(groupID); 2085 sog.SetOwnerId(groupID);
2182 sog.ApplyNextOwnerPermissions(); 2086 sog.ApplyNextOwnerPermissions();
2183 } 2087 }
2184
2185 } 2088 }
2186 2089
2187 foreach (uint localID in localIDs) 2090 foreach (uint localID in localIDs)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index e25b1f1..c511774 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -156,21 +156,30 @@ namespace OpenSim.Region.Framework.Scenes
156 } 156 }
157 break; 157 break;
158 } 158 }
159 else 159 else
160 { 160 {
161 // We also need to check the children of this prim as they 161 // We also need to check the children of this prim as they
162 // can be selected as well and send property information 162 // can be selected as well and send property information
163 bool foundPrim = false; 163 bool foundPrim = false;
164 foreach (KeyValuePair<UUID, SceneObjectPart> child in ((SceneObjectGroup) ent).Children) 164
165 { 165 SceneObjectGroup sog = ent as SceneObjectGroup;
166 if (child.Value.LocalId == primLocalID) 166
167 { 167 List<SceneObjectPart> partList = null;
168 child.Value.GetProperties(remoteClient); 168 lock (sog.Children)
169 foundPrim = true; 169 partList = new List<SceneObjectPart>(sog.Children.Values);
170 break; 170
171 } 171 foreach (SceneObjectPart part in partList)
172 } 172 {
173 if (foundPrim) break; 173 if (part.LocalId == primLocalID)
174 {
175 part.GetProperties(remoteClient);
176 foundPrim = true;
177 break;
178 }
179 }
180
181 if (foundPrim)
182 break;
174 } 183 }
175 } 184 }
176 } 185 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 736b696..9fea2a0 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -42,7 +42,6 @@ using OpenMetaverse.Imaging;
42using OpenSim.Framework; 42using OpenSim.Framework;
43using OpenSim.Services.Interfaces; 43using OpenSim.Services.Interfaces;
44using OpenSim.Framework.Communications; 44using OpenSim.Framework.Communications;
45
46using OpenSim.Framework.Console; 45using OpenSim.Framework.Console;
47using OpenSim.Region.Framework.Interfaces; 46using OpenSim.Region.Framework.Interfaces;
48using OpenSim.Region.Framework.Scenes.Scripting; 47using OpenSim.Region.Framework.Scenes.Scripting;
@@ -399,6 +398,7 @@ namespace OpenSim.Region.Framework.Scenes
399 private bool m_firstHeartbeat = true; 398 private bool m_firstHeartbeat = true;
400 399
401 private object m_deleting_scene_object = new object(); 400 private object m_deleting_scene_object = new object();
401 private object m_cleaningAttachments = new object();
402 402
403 // the minimum time that must elapse before a changed object will be considered for persisted 403 // the minimum time that must elapse before a changed object will be considered for persisted
404 public long m_dontPersistBefore = DEFAULT_MIN_TIME_FOR_PERSISTENCE * 10000000L; 404 public long m_dontPersistBefore = DEFAULT_MIN_TIME_FOR_PERSISTENCE * 10000000L;
@@ -1790,8 +1790,9 @@ namespace OpenSim.Region.Framework.Scenes
1790 1790
1791 if (group.RootPart == null) 1791 if (group.RootPart == null)
1792 { 1792 {
1793 m_log.ErrorFormat("[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children", 1793 m_log.ErrorFormat(
1794 group.Children == null ? 0 : group.Children.Count); 1794 "[SCENE]: Found a SceneObjectGroup with m_rootPart == null and {0} children",
1795 group.Children == null ? 0 : group.PrimCount);
1795 } 1796 }
1796 1797
1797 AddRestoredSceneObject(group, true, true); 1798 AddRestoredSceneObject(group, true, true);
@@ -2050,7 +2051,24 @@ namespace OpenSim.Region.Framework.Scenes
2050 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 2051 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
2051 { 2052 {
2052 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); 2053 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates);
2053 } 2054 }
2055
2056 /// <summary>
2057 /// Add a newly created object to the scene.
2058 /// </summary>
2059 ///
2060 /// This method does not send updates to the client - callers need to handle this themselves.
2061 /// <param name="sceneObject"></param>
2062 /// <param name="attachToBackup"></param>
2063 /// <param name="pos">Position of the object</param>
2064 /// <param name="rot">Rotation of the object</param>
2065 /// <param name="vel">Velocity of the object. This parameter only has an effect if the object is physical</param>
2066 /// <returns></returns>
2067 public bool AddNewSceneObject(
2068 SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel)
2069 {
2070 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel);
2071 }
2054 2072
2055 /// <summary> 2073 /// <summary>
2056 /// Delete every object from the scene. This does not include attachments worn by avatars. 2074 /// Delete every object from the scene. This does not include attachments worn by avatars.
@@ -2113,7 +2131,11 @@ namespace OpenSim.Region.Framework.Scenes
2113 group.RemoveScriptInstances(true); 2131 group.RemoveScriptInstances(true);
2114 } 2132 }
2115 2133
2116 foreach (SceneObjectPart part in group.Children.Values) 2134 List<SceneObjectPart> partList = null;
2135 lock (group.Children)
2136 partList = new List<SceneObjectPart>(group.Children.Values);
2137
2138 foreach (SceneObjectPart part in partList)
2117 { 2139 {
2118 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0)) 2140 if (part.IsJoint() && ((part.Flags & PrimFlags.Physics) != 0))
2119 { 2141 {
@@ -2125,6 +2147,7 @@ namespace OpenSim.Region.Framework.Scenes
2125 part.PhysActor = null; 2147 part.PhysActor = null;
2126 } 2148 }
2127 } 2149 }
2150
2128// if (rootPart.PhysActor != null) 2151// if (rootPart.PhysActor != null)
2129// { 2152// {
2130// PhysicsScene.RemovePrim(rootPart.PhysActor); 2153// PhysicsScene.RemovePrim(rootPart.PhysActor);
@@ -2481,14 +2504,16 @@ namespace OpenSim.Region.Framework.Scenes
2481 2504
2482 // Force allocation of new LocalId 2505 // Force allocation of new LocalId
2483 // 2506 //
2484 foreach (SceneObjectPart p in sceneObject.Children.Values) 2507 lock (sceneObject.Children)
2485 p.LocalId = 0; 2508 {
2509 foreach (SceneObjectPart p in sceneObject.Children.Values)
2510 p.LocalId = 0;
2511 }
2486 2512
2487 if (sceneObject.IsAttachmentCheckFull()) // Attachment 2513 if (sceneObject.IsAttachmentCheckFull()) // Attachment
2488 { 2514 {
2489 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); 2515 sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez);
2490 sceneObject.RootPart.AddFlag(PrimFlags.Phantom); 2516 sceneObject.RootPart.AddFlag(PrimFlags.Phantom);
2491
2492 2517
2493 // Don't sent a full update here because this will cause full updates to be sent twice for 2518 // Don't sent a full update here because this will cause full updates to be sent twice for
2494 // attachments on region crossings, resulting in viewer glitches. 2519 // attachments on region crossings, resulting in viewer glitches.
@@ -2502,7 +2527,6 @@ namespace OpenSim.Region.Framework.Scenes
2502 2527
2503 if (sp != null) 2528 if (sp != null)
2504 { 2529 {
2505
2506 SceneObjectGroup grp = sceneObject; 2530 SceneObjectGroup grp = sceneObject;
2507 2531
2508 m_log.DebugFormat( 2532 m_log.DebugFormat(
@@ -3210,6 +3234,7 @@ namespace OpenSim.Region.Framework.Scenes
3210 m_log.Debug("[Scene] Beginning OnRemovePresence"); 3234 m_log.Debug("[Scene] Beginning OnRemovePresence");
3211 m_eventManager.TriggerOnRemovePresence(agentID); 3235 m_eventManager.TriggerOnRemovePresence(agentID);
3212 m_log.Debug("[Scene] Finished OnRemovePresence"); 3236 m_log.Debug("[Scene] Finished OnRemovePresence");
3237
3213 ForEachClient( 3238 ForEachClient(
3214 delegate(IClientAPI client) 3239 delegate(IClientAPI client)
3215 { 3240 {
@@ -3245,6 +3270,7 @@ namespace OpenSim.Region.Framework.Scenes
3245 } 3270 }
3246 m_log.Debug("[Scene] Done. Firing RemoveCircuit"); 3271 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3247 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3272 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3273 CleanDroppedAttachments();
3248 m_log.Debug("[Scene] The avatar has left the building"); 3274 m_log.Debug("[Scene] The avatar has left the building");
3249 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3275 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3250 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3276 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
@@ -3443,6 +3469,8 @@ namespace OpenSim.Region.Framework.Scenes
3443 3469
3444 if (vialogin) 3470 if (vialogin)
3445 { 3471 {
3472 CleanDroppedAttachments();
3473
3446 if (TestBorderCross(agent.startpos, Cardinals.E)) 3474 if (TestBorderCross(agent.startpos, Cardinals.E))
3447 { 3475 {
3448 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); 3476 Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E);
@@ -3694,18 +3722,6 @@ namespace OpenSim.Region.Framework.Scenes
3694 return true; 3722 return true;
3695 } 3723 }
3696 3724
3697 private ILandObject GetParcelAtPoint(float x, float y)
3698 {
3699 foreach (var parcel in AllParcels())
3700 {
3701 if (parcel.ContainsPoint((int)x,(int)y))
3702 {
3703 return parcel;
3704 }
3705 }
3706 return null;
3707 }
3708
3709 /// <summary> 3725 /// <summary>
3710 /// Update an AgentCircuitData object with new information 3726 /// Update an AgentCircuitData object with new information
3711 /// </summary> 3727 /// </summary>
@@ -5041,5 +5057,45 @@ namespace OpenSim.Region.Framework.Scenes
5041 throw new Exception(error); 5057 throw new Exception(error);
5042 } 5058 }
5043 } 5059 }
5060
5061 public void CleanDroppedAttachments()
5062 {
5063 List<SceneObjectGroup> objectsToDelete =
5064 new List<SceneObjectGroup>();
5065
5066 lock (m_cleaningAttachments)
5067 {
5068 ForEachSOG(delegate (SceneObjectGroup grp)
5069 {
5070 if (grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5071 {
5072 UUID agentID = grp.OwnerID;
5073 if (agentID == UUID.Zero)
5074 {
5075 objectsToDelete.Add(grp);
5076 return;
5077 }
5078
5079 ScenePresence sp = GetScenePresence(agentID);
5080 if (sp == null)
5081 {
5082 objectsToDelete.Add(grp);
5083 return;
5084 }
5085 }
5086 });
5087 }
5088
5089 if (objectsToDelete.Count > 0)
5090 {
5091 m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count);
5092 foreach (SceneObjectGroup grp in objectsToDelete)
5093 {
5094 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5095 DeleteSceneObject(grp, true);
5096 }
5097 m_log.Debug("[SCENE]: Finished dropped attachment deletion");
5098 }
5099 }
5044 } 5100 }
5045} 5101}
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 59e4037..1293d5d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -70,7 +70,7 @@ namespace OpenSim.Region.Framework.Scenes
70 /// <summary> 70 /// <summary>
71 /// A user will arrive shortly, set up appropriate credentials so it can connect 71 /// A user will arrive shortly, set up appropriate credentials so it can connect
72 /// </summary> 72 /// </summary>
73 public event ExpectUserDelegate OnExpectUser; 73// public event ExpectUserDelegate OnExpectUser;
74 74
75 /// <summary> 75 /// <summary>
76 /// A Prim will arrive shortly 76 /// A Prim will arrive shortly
@@ -80,7 +80,7 @@ namespace OpenSim.Region.Framework.Scenes
80 /// <summary> 80 /// <summary>
81 /// A new prim has arrived 81 /// A new prim has arrived
82 /// </summary> 82 /// </summary>
83 public event PrimCrossing OnPrimCrossingIntoRegion; 83// public event PrimCrossing OnPrimCrossingIntoRegion;
84 84
85 ///// <summary> 85 ///// <summary>
86 ///// A New Region is up and available 86 ///// A New Region is up and available
@@ -90,7 +90,7 @@ namespace OpenSim.Region.Framework.Scenes
90 /// <summary> 90 /// <summary>
91 /// We have a child agent for this avatar and we're getting a status update about it 91 /// We have a child agent for this avatar and we're getting a status update about it
92 /// </summary> 92 /// </summary>
93 public event ChildAgentUpdate OnChildAgentUpdate; 93// public event ChildAgentUpdate OnChildAgentUpdate;
94 //public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar; 94 //public event RemoveKnownRegionsFromAvatarList OnRemoveKnownRegionFromAvatar;
95 95
96 /// <summary> 96 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 94ec534..b86a564 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -104,7 +104,6 @@ namespace OpenSim.Region.Framework.Scenes
104 104
105 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalID = new Dictionary<uint, SceneObjectGroup>(); 105 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalID = new Dictionary<uint, SceneObjectGroup>();
106 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>(); 106 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>();
107 private readonly Object m_dictionary_lock = new Object();
108 107
109 private Object m_updateLock = new Object(); 108 private Object m_updateLock = new Object();
110 109
@@ -150,11 +149,10 @@ namespace OpenSim.Region.Framework.Scenes
150 m_scenePresencesLock.ExitWriteLock(); 149 m_scenePresencesLock.ExitWriteLock();
151 } 150 }
152 151
153 lock (m_dictionary_lock) 152 lock (SceneObjectGroupsByFullID)
154 {
155 SceneObjectGroupsByFullID.Clear(); 153 SceneObjectGroupsByFullID.Clear();
154 lock (SceneObjectGroupsByLocalID)
156 SceneObjectGroupsByLocalID.Clear(); 155 SceneObjectGroupsByLocalID.Clear();
157 }
158 156
159 Entities.Clear(); 157 Entities.Clear();
160 } 158 }
@@ -314,6 +312,42 @@ namespace OpenSim.Region.Framework.Scenes
314 312
315 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); 313 return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates);
316 } 314 }
315
316 /// <summary>
317 /// Add a newly created object to the scene.
318 /// </summary>
319 ///
320 /// This method does not send updates to the client - callers need to handle this themselves.
321 /// <param name="sceneObject"></param>
322 /// <param name="attachToBackup"></param>
323 /// <param name="pos">Position of the object</param>
324 /// <param name="rot">Rotation of the object</param>
325 /// <param name="vel">Velocity of the object. This parameter only has an effect if the object is physical</param>
326 /// <returns></returns>
327 public bool AddNewSceneObject(
328 SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel)
329 {
330 AddNewSceneObject(sceneObject, true, false);
331
332 // we set it's position in world.
333 sceneObject.AbsolutePosition = pos;
334
335 if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim)
336 {
337 sceneObject.ClearPartAttachmentData();
338 }
339
340 sceneObject.UpdateGroupRotationR(rot);
341
342 //group.ApplyPhysics(m_physicalPrim);
343 if (sceneObject.RootPart.PhysActor != null && sceneObject.RootPart.PhysActor.IsPhysical && vel != Vector3.Zero)
344 {
345 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
346 sceneObject.Velocity = vel;
347 }
348
349 return true;
350 }
317 351
318 /// <summary> 352 /// <summary>
319 /// Add an object to the scene. This will both update the scene, and send information about the 353 /// Add an object to the scene. This will both update the scene, and send information about the
@@ -350,50 +384,53 @@ namespace OpenSim.Region.Framework.Scenes
350// "[SCENE GRAPH]: Adding object {0} {1} to region {2}", 384// "[SCENE GRAPH]: Adding object {0} {1} to region {2}",
351// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName); 385// sceneObject.Name, sceneObject.UUID, m_parentScene.RegionInfo.RegionName);
352 386
353 if (m_parentScene.m_clampPrimSize) 387 lock (sceneObject.Children)
354 { 388 {
355 foreach (SceneObjectPart part in sceneObject.Children.Values) 389 if (m_parentScene.m_clampPrimSize)
356 { 390 {
357 Vector3 scale = part.Shape.Scale; 391 foreach (SceneObjectPart part in sceneObject.Children.Values)
358 392 {
359 if (scale.X > m_parentScene.m_maxNonphys) 393 Vector3 scale = part.Shape.Scale;
360 scale.X = m_parentScene.m_maxNonphys; 394
361 if (scale.Y > m_parentScene.m_maxNonphys) 395 if (scale.X > m_parentScene.m_maxNonphys)
362 scale.Y = m_parentScene.m_maxNonphys; 396 scale.X = m_parentScene.m_maxNonphys;
363 if (scale.Z > m_parentScene.m_maxNonphys) 397 if (scale.Y > m_parentScene.m_maxNonphys)
364 scale.Z = m_parentScene.m_maxNonphys; 398 scale.Y = m_parentScene.m_maxNonphys;
365 399 if (scale.Z > m_parentScene.m_maxNonphys)
366 part.Shape.Scale = scale; 400 scale.Z = m_parentScene.m_maxNonphys;
401
402 part.Shape.Scale = scale;
403 }
367 } 404 }
405
406 m_numPrim += sceneObject.Children.Count;
368 } 407 }
369 408
370 sceneObject.AttachToScene(m_parentScene); 409 sceneObject.AttachToScene(m_parentScene);
371 410
372 if (sendClientUpdates) 411 if (sendClientUpdates)
373 sceneObject.ScheduleGroupForFullUpdate(); 412 sceneObject.ScheduleGroupForFullUpdate();
374 413
375 Entities.Add(sceneObject); 414 Entities.Add(sceneObject);
376 m_numPrim += sceneObject.Children.Count;
377 415
378 if (attachToBackup) 416 if (attachToBackup)
379 {
380 sceneObject.AttachToBackup(); 417 sceneObject.AttachToBackup();
381 }
382 418
383 if (OnObjectCreate != null) 419 if (OnObjectCreate != null)
384 {
385 OnObjectCreate(sceneObject); 420 OnObjectCreate(sceneObject);
386 }
387 421
388 lock (m_dictionary_lock) 422 lock (SceneObjectGroupsByFullID)
389 { 423 {
390 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; 424 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
391 SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject;
392 foreach (SceneObjectPart part in sceneObject.Children.Values) 425 foreach (SceneObjectPart part in sceneObject.Children.Values)
393 {
394 SceneObjectGroupsByFullID[part.UUID] = sceneObject; 426 SceneObjectGroupsByFullID[part.UUID] = sceneObject;
427 }
428
429 lock (SceneObjectGroupsByLocalID)
430 {
431 SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject;
432 foreach (SceneObjectPart part in sceneObject.Children.Values)
395 SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; 433 SceneObjectGroupsByLocalID[part.LocalId] = sceneObject;
396 }
397 } 434 }
398 } 435 }
399 436
@@ -408,24 +445,32 @@ namespace OpenSim.Region.Framework.Scenes
408 { 445 {
409 if (Entities.ContainsKey(uuid)) 446 if (Entities.ContainsKey(uuid))
410 { 447 {
448 SceneObjectGroup grp = (SceneObjectGroup)Entities[uuid];
449
411 if (!resultOfObjectLinked) 450 if (!resultOfObjectLinked)
412 { 451 {
413 m_numPrim -= ((SceneObjectGroup) Entities[uuid]).Children.Count; 452 m_numPrim -= grp.PrimCount;
414 453
415 if ((((SceneObjectGroup)Entities[uuid]).RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 454 if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
416 { 455 RemovePhysicalPrim(grp.PrimCount);
417 RemovePhysicalPrim(((SceneObjectGroup)Entities[uuid]).Children.Count);
418 }
419 } 456 }
420 457
421 if (OnObjectRemove != null) 458 if (OnObjectRemove != null)
422 OnObjectRemove(Entities[uuid]); 459 OnObjectRemove(Entities[uuid]);
423 460
424 lock (m_dictionary_lock) 461 lock (SceneObjectGroupsByFullID)
425 { 462 {
426 SceneObjectGroupsByFullID.Remove(uuid); 463 foreach (SceneObjectPart part in grp.Children.Values)
427 SceneObjectGroupsByLocalID.Remove(((SceneObjectGroup)Entities[uuid]).LocalId); 464 SceneObjectGroupsByFullID.Remove(part.UUID);
465 SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID);
428 } 466 }
467 lock (SceneObjectGroupsByLocalID)
468 {
469 foreach (SceneObjectPart part in grp.Children.Values)
470 SceneObjectGroupsByLocalID.Remove(part.LocalId);
471 SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId);
472 }
473
429 Entities.Remove(uuid); 474 Entities.Remove(uuid);
430 //SceneObjectGroup part; 475 //SceneObjectGroup part;
431 //((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) 476 //((part.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics)
@@ -884,7 +929,9 @@ namespace OpenSim.Region.Framework.Scenes
884 { 929 {
885 if (SceneObjectGroupsByLocalID.TryGetValue(localID, out sog)) 930 if (SceneObjectGroupsByLocalID.TryGetValue(localID, out sog))
886 { 931 {
887 return sog; 932 if (sog.HasChildPrim(localID))
933 return sog;
934 SceneObjectGroupsByLocalID.Remove(localID);
888 } 935 }
889 } 936 }
890 937
@@ -920,7 +967,13 @@ namespace OpenSim.Region.Framework.Scenes
920 { 967 {
921 if (SceneObjectGroupsByFullID.TryGetValue(fullID, out sog)) 968 if (SceneObjectGroupsByFullID.TryGetValue(fullID, out sog))
922 { 969 {
923 return sog; 970 lock (sog.Children)
971 {
972 if (sog.Children.ContainsKey(fullID))
973 return sog;
974 }
975
976 SceneObjectGroupsByFullID.Remove(fullID);
924 } 977 }
925 } 978 }
926 979
@@ -1087,9 +1140,11 @@ namespace OpenSim.Region.Framework.Scenes
1087 /// <param name="action"></param> 1140 /// <param name="action"></param>
1088 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1141 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1089 { 1142 {
1090 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1143 List<EntityBase> objlist = Entities.GetAllByType<SceneObjectGroup>();
1091 foreach (SceneObjectGroup obj in objlist) 1144 foreach (EntityBase ent in objlist)
1092 { 1145 {
1146 SceneObjectGroup obj = (SceneObjectGroup)ent;
1147
1093 try 1148 try
1094 { 1149 {
1095 action(obj); 1150 action(obj);
@@ -1293,37 +1348,21 @@ namespace OpenSim.Region.Framework.Scenes
1293 /// <param name="localID"></param> 1348 /// <param name="localID"></param>
1294 /// <param name="pos"></param> 1349 /// <param name="pos"></param>
1295 /// <param name="remoteClient"></param> 1350 /// <param name="remoteClient"></param>
1296 protected internal void UpdatePrimPosition(uint localID, Vector3 pos, IClientAPI remoteClient) 1351 public void UpdatePrimPosition(uint localID, Vector3 pos, IClientAPI remoteClient)
1297 { 1352 {
1298 SceneObjectGroup group = GetGroupByPrim(localID); 1353 SceneObjectGroup group = GetGroupByPrim(localID);
1354
1299 if (group != null) 1355 if (group != null)
1300 { 1356 {
1301
1302 // Vector3 oldPos = group.AbsolutePosition;
1303 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1357 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1304 { 1358 {
1305 1359 if (m_parentScene.AttachmentsModule != null)
1306 // If this is an attachment, then we need to save the modified 1360 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(remoteClient, group, pos);
1307 // object back into the avatar's inventory. First we save the
1308 // attachment point information, then we update the relative
1309 // positioning (which caused this method to get driven in the
1310 // first place. Then we have to mark the object as NOT an
1311 // attachment. This is necessary in order to correctly save
1312 // and retrieve GroupPosition information for the attachment.
1313 // Then we save the asset back into the appropriate inventory
1314 // entry. Finally, we restore the object's attachment status.
1315
1316 byte attachmentPoint = group.GetAttachmentPoint();
1317 group.UpdateGroupPosition(pos);
1318 group.RootPart.IsAttachment = false;
1319 group.AbsolutePosition = group.RootPart.AttachedPos;
1320 m_parentScene.UpdateKnownItem(remoteClient, group, group.GetFromItemID(), group.OwnerID);
1321 group.SetAttachmentPoint(attachmentPoint);
1322
1323 } 1361 }
1324 else 1362 else
1325 { 1363 {
1326 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId) && m_parentScene.Permissions.CanObjectEntry(group.UUID, false, pos)) 1364 if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)
1365 && m_parentScene.Permissions.CanObjectEntry(group.UUID, false, pos))
1327 { 1366 {
1328 group.UpdateGroupPosition(pos); 1367 group.UpdateGroupPosition(pos);
1329 } 1368 }
@@ -1332,14 +1371,19 @@ namespace OpenSim.Region.Framework.Scenes
1332 } 1371 }
1333 1372
1334 /// <summary> 1373 /// <summary>
1335 /// 1374 /// Update the texture entry of the given prim.
1336 /// </summary> 1375 /// </summary>
1376 ///
1377 /// A texture entry is an object that contains details of all the textures of the prim's face. In this case,
1378 /// the texture is given in its byte serialized form.
1379 ///
1337 /// <param name="localID"></param> 1380 /// <param name="localID"></param>
1338 /// <param name="texture"></param> 1381 /// <param name="texture"></param>
1339 /// <param name="remoteClient"></param> 1382 /// <param name="remoteClient"></param>
1340 protected internal void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient) 1383 protected internal void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient)
1341 { 1384 {
1342 SceneObjectGroup group = GetGroupByPrim(localID); 1385 SceneObjectGroup group = GetGroupByPrim(localID);
1386
1343 if (group != null) 1387 if (group != null)
1344 { 1388 {
1345 if (m_parentScene.Permissions.CanEditObject(group.UUID,remoteClient.AgentId)) 1389 if (m_parentScene.Permissions.CanEditObject(group.UUID,remoteClient.AgentId))
@@ -1630,7 +1674,7 @@ namespace OpenSim.Region.Framework.Scenes
1630 { 1674 {
1631 if (part != null) 1675 if (part != null)
1632 { 1676 {
1633 if (part.ParentGroup.Children.Count != 1) // Skip single 1677 if (part.ParentGroup.PrimCount != 1) // Skip single
1634 { 1678 {
1635 if (part.LinkNum < 2) // Root 1679 if (part.LinkNum < 2) // Root
1636 rootParts.Add(part); 1680 rootParts.Add(part);
@@ -1669,8 +1713,15 @@ namespace OpenSim.Region.Framework.Scenes
1669 // However, editing linked parts and unlinking may be different 1713 // However, editing linked parts and unlinking may be different
1670 // 1714 //
1671 SceneObjectGroup group = root.ParentGroup; 1715 SceneObjectGroup group = root.ParentGroup;
1672 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Children.Values); 1716
1673 int numChildren = group.Children.Count; 1717 List<SceneObjectPart> newSet = null;
1718 int numChildren = -1;
1719
1720 lock (group.Children)
1721 {
1722 newSet = new List<SceneObjectPart>(group.Children.Values);
1723 numChildren = group.PrimCount;
1724 }
1674 1725
1675 // If there are prims left in a link set, but the root is 1726 // If there are prims left in a link set, but the root is
1676 // slated for unlink, we need to do this 1727 // slated for unlink, we need to do this
@@ -1722,8 +1773,6 @@ namespace OpenSim.Region.Framework.Scenes
1722 SceneObjectPart newRoot = newSet[0]; 1773 SceneObjectPart newRoot = newSet[0];
1723 newSet.RemoveAt(0); 1774 newSet.RemoveAt(0);
1724 1775
1725 List<uint> linkIDs = new List<uint>();
1726
1727 foreach (SceneObjectPart newChild in newSet) 1776 foreach (SceneObjectPart newChild in newSet)
1728 newChild.UpdateFlag = 0; 1777 newChild.UpdateFlag = 0;
1729 1778
@@ -1760,12 +1809,17 @@ namespace OpenSim.Region.Framework.Scenes
1760 { 1809 {
1761 if (ent is SceneObjectGroup) 1810 if (ent is SceneObjectGroup)
1762 { 1811 {
1763 foreach (KeyValuePair<UUID, SceneObjectPart> subent in ((SceneObjectGroup)ent).Children) 1812 SceneObjectGroup sog = ent as SceneObjectGroup;
1813
1814 lock (sog.Children)
1764 { 1815 {
1765 if (subent.Value.LocalId == localID) 1816 foreach (KeyValuePair<UUID, SceneObjectPart> subent in sog.Children)
1766 { 1817 {
1767 objid = subent.Key; 1818 if (subent.Value.LocalId == localID)
1768 obj = subent.Value; 1819 {
1820 objid = subent.Key;
1821 obj = subent.Value;
1822 }
1769 } 1823 }
1770 } 1824 }
1771 } 1825 }
@@ -1830,7 +1884,8 @@ namespace OpenSim.Region.Framework.Scenes
1830 SceneObjectGroup original = GetGroupByPrim(originalPrimID); 1884 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1831 if (original != null) 1885 if (original != null)
1832 { 1886 {
1833 if (m_parentScene.Permissions.CanDuplicateObject(original.Children.Count, original.UUID, AgentID, original.AbsolutePosition)) 1887 if (m_parentScene.Permissions.CanDuplicateObject(
1888 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1834 { 1889 {
1835 SceneObjectGroup copy = original.Copy(true); 1890 SceneObjectGroup copy = original.Copy(true);
1836 copy.AbsolutePosition = copy.AbsolutePosition + offset; 1891 copy.AbsolutePosition = copy.AbsolutePosition + offset;
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 9b66fad..5a586d4 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -360,7 +360,7 @@ namespace OpenSim.Region.Framework.Scenes
360 /// </summary> 360 /// </summary>
361 public int PrimCount 361 public int PrimCount
362 { 362 {
363 get { return m_parts.Count; } 363 get { lock (m_parts) { return m_parts.Count; } }
364 } 364 }
365 365
366 protected Quaternion m_rotation = Quaternion.Identity; 366 protected Quaternion m_rotation = Quaternion.Identity;
@@ -398,6 +398,9 @@ namespace OpenSim.Region.Framework.Scenes
398 398
399 /// <value> 399 /// <value>
400 /// The parts of this scene object group. You must lock this property before using it. 400 /// The parts of this scene object group. You must lock this property before using it.
401 /// If you're doing anything other than reading values, please take a copy of the values rather than locking
402 /// the dictionary for the entirety of the operation. This increases liveness and reduces the danger of deadlock
403 /// If you want to know the number of children, consider using the PrimCount property instead
401 /// </value> 404 /// </value>
402 public Dictionary<UUID, SceneObjectPart> Children 405 public Dictionary<UUID, SceneObjectPart> Children
403 { 406 {
@@ -521,7 +524,16 @@ namespace OpenSim.Region.Framework.Scenes
521 public override UUID UUID 524 public override UUID UUID
522 { 525 {
523 get { return m_rootPart.UUID; } 526 get { return m_rootPart.UUID; }
524 set { m_rootPart.UUID = value; } 527 set
528 {
529 m_rootPart.UUID = value;
530
531 lock (m_parts)
532 {
533 m_parts.Remove(m_rootPart.UUID);
534 m_parts.Add(m_rootPart.UUID, m_rootPart);
535 }
536 }
525 } 537 }
526 538
527 public UUID OwnerID 539 public UUID OwnerID
@@ -742,21 +754,23 @@ namespace OpenSim.Region.Framework.Scenes
742 if (m_rootPart.LocalId == 0) 754 if (m_rootPart.LocalId == 0)
743 m_rootPart.LocalId = m_scene.AllocateLocalId(); 755 m_rootPart.LocalId = m_scene.AllocateLocalId();
744 756
745 // No need to lock here since the object isn't yet in a scene 757 lock (m_parts)
746 foreach (SceneObjectPart part in m_parts.Values)
747 { 758 {
748 if (Object.ReferenceEquals(part, m_rootPart)) 759 foreach (SceneObjectPart part in m_parts.Values)
749 {
750 continue;
751 }
752
753 if (part.LocalId == 0)
754 { 760 {
755 part.LocalId = m_scene.AllocateLocalId(); 761 if (Object.ReferenceEquals(part, m_rootPart))
762 {
763 continue;
764 }
765
766 if (part.LocalId == 0)
767 {
768 part.LocalId = m_scene.AllocateLocalId();
769 }
770
771 part.ParentID = m_rootPart.LocalId;
772 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
756 } 773 }
757
758 part.ParentID = m_rootPart.LocalId;
759 //m_log.DebugFormat("[SCENE]: Given local id {0} to part {1}, linknum {2}, parent {3} {4}", part.LocalId, part.UUID, part.LinkNum, part.ParentID, part.ParentUUID);
760 } 774 }
761 775
762 ApplyPhysics(m_scene.m_physicalPrim); 776 ApplyPhysics(m_scene.m_physicalPrim);
@@ -1238,9 +1252,12 @@ namespace OpenSim.Region.Framework.Scenes
1238 m_rootPart.AttachedAvatar = agentID; 1252 m_rootPart.AttachedAvatar = agentID;
1239 1253
1240 //Anakin Lohner bug #3839 1254 //Anakin Lohner bug #3839
1241 foreach (SceneObjectPart p in m_parts.Values) 1255 lock (m_parts)
1242 { 1256 {
1243 p.AttachedAvatar = agentID; 1257 foreach (SceneObjectPart p in m_parts.Values)
1258 {
1259 p.AttachedAvatar = agentID;
1260 }
1244 } 1261 }
1245 1262
1246 if (m_rootPart.PhysActor != null) 1263 if (m_rootPart.PhysActor != null)
@@ -1308,10 +1325,14 @@ namespace OpenSim.Region.Framework.Scenes
1308 1325
1309 AbsolutePosition = detachedpos; 1326 AbsolutePosition = detachedpos;
1310 m_rootPart.AttachedAvatar = UUID.Zero; 1327 m_rootPart.AttachedAvatar = UUID.Zero;
1311 //Anakin Lohner bug #3839 1328
1312 foreach (SceneObjectPart p in m_parts.Values) 1329 //Anakin Lohner bug #3839
1330 lock (m_parts)
1313 { 1331 {
1314 p.AttachedAvatar = UUID.Zero; 1332 foreach (SceneObjectPart p in m_parts.Values)
1333 {
1334 p.AttachedAvatar = UUID.Zero;
1335 }
1315 } 1336 }
1316 1337
1317 m_rootPart.SetParentLocalId(0); 1338 m_rootPart.SetParentLocalId(0);
@@ -1337,10 +1358,14 @@ namespace OpenSim.Region.Framework.Scenes
1337 } 1358 }
1338 1359
1339 m_rootPart.AttachedAvatar = UUID.Zero; 1360 m_rootPart.AttachedAvatar = UUID.Zero;
1361
1340 //Anakin Lohner bug #3839 1362 //Anakin Lohner bug #3839
1341 foreach (SceneObjectPart p in m_parts.Values) 1363 lock (m_parts)
1342 { 1364 {
1343 p.AttachedAvatar = UUID.Zero; 1365 foreach (SceneObjectPart p in m_parts.Values)
1366 {
1367 p.AttachedAvatar = UUID.Zero;
1368 }
1344 } 1369 }
1345 1370
1346 m_rootPart.SetParentLocalId(0); 1371 m_rootPart.SetParentLocalId(0);
@@ -1406,9 +1431,8 @@ namespace OpenSim.Region.Framework.Scenes
1406 part.ParentID = 0; 1431 part.ParentID = 0;
1407 part.LinkNum = 0; 1432 part.LinkNum = 0;
1408 1433
1409 // No locking required since the SOG should not be in the scene yet - one can't change root parts after 1434 lock (m_parts)
1410 // the scene object has been attached to the scene 1435 m_parts.Add(m_rootPart.UUID, m_rootPart);
1411 m_parts.Add(m_rootPart.UUID, m_rootPart);
1412 } 1436 }
1413 1437
1414 /// <summary> 1438 /// <summary>
@@ -1928,14 +1952,14 @@ namespace OpenSim.Region.Framework.Scenes
1928 } 1952 }
1929 1953
1930 /// <summary> 1954 /// <summary>
1931 /// 1955 /// Copy the given part as the root part of this scene object.
1932 /// </summary> 1956 /// </summary>
1933 /// <param name="part"></param> 1957 /// <param name="part"></param>
1934 /// <param name="cAgentID"></param> 1958 /// <param name="cAgentID"></param>
1935 /// <param name="cGroupID"></param> 1959 /// <param name="cGroupID"></param>
1936 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 1960 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1937 { 1961 {
1938 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed)); 1962 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
1939 } 1963 }
1940 1964
1941 public void ScriptSetPhysicsStatus(bool UsePhysics) 1965 public void ScriptSetPhysicsStatus(bool UsePhysics)
@@ -2234,14 +2258,15 @@ namespace OpenSim.Region.Framework.Scenes
2234 /// </summary> 2258 /// </summary>
2235 public void ResetIDs() 2259 public void ResetIDs()
2236 { 2260 {
2237 // As this is only ever called for prims which are not currently part of the scene (and hence 2261 lock (m_parts)
2238 // not accessible by clients), there should be no need to lock
2239 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values);
2240 m_parts.Clear();
2241 foreach (SceneObjectPart part in partsList)
2242 { 2262 {
2243 part.ResetIDs(part.LinkNum); // Don't change link nums 2263 List<SceneObjectPart> partsList = new List<SceneObjectPart>(m_parts.Values);
2244 m_parts.Add(part.UUID, part); 2264 m_parts.Clear();
2265 foreach (SceneObjectPart part in partsList)
2266 {
2267 part.ResetIDs(part.LinkNum); // Don't change link nums
2268 m_parts.Add(part.UUID, part);
2269 }
2245 } 2270 }
2246 } 2271 }
2247 2272
@@ -2283,29 +2308,29 @@ namespace OpenSim.Region.Framework.Scenes
2283 // return; 2308 // return;
2284 2309
2285 lockPartsForRead(true); 2310 lockPartsForRead(true);
2286 {
2287 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
2288 2311
2289 if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f)) 2312 bool UsePhysics = ((RootPart.Flags & PrimFlags.Physics) != 0);
2290 {
2291 m_rootPart.UpdateFlag = 1;
2292 lastPhysGroupPos = AbsolutePosition;
2293 }
2294 2313
2295 if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f)) 2314 if (UsePhysics && !AbsolutePosition.ApproxEquals(lastPhysGroupPos, 0.02f))
2296 { 2315 {
2297 m_rootPart.UpdateFlag = 1; 2316 m_rootPart.UpdateFlag = 1;
2298 lastPhysGroupRot = GroupRotation; 2317 lastPhysGroupPos = AbsolutePosition;
2299 } 2318 }
2300 2319
2301 foreach (SceneObjectPart part in m_parts.Values) 2320 if (UsePhysics && !GroupRotation.ApproxEquals(lastPhysGroupRot, 0.1f))
2302 { 2321 {
2303 if (!IsSelected) 2322 m_rootPart.UpdateFlag = 1;
2304 part.UpdateLookAt(); 2323 lastPhysGroupRot = GroupRotation;
2324 }
2305 2325
2306 part.SendScheduledUpdates(); 2326 List<SceneObjectPart> partList = null;
2307 2327 partList = new List<SceneObjectPart>(m_parts.Values);
2308 } 2328
2329 foreach (SceneObjectPart part in partList)
2330 {
2331 if (!IsSelected)
2332 part.UpdateLookAt();
2333 part.SendScheduledUpdates();
2309 } 2334 }
2310 lockPartsForRead(false); 2335 lockPartsForRead(false);
2311 } 2336 }
@@ -2479,10 +2504,15 @@ namespace OpenSim.Region.Framework.Scenes
2479 public SceneObjectPart GetChildPart(UUID primID) 2504 public SceneObjectPart GetChildPart(UUID primID)
2480 { 2505 {
2481 SceneObjectPart childPart = null; 2506 SceneObjectPart childPart = null;
2482 if (m_parts.ContainsKey(primID)) 2507
2508 lock (m_parts)
2483 { 2509 {
2484 childPart = m_parts[primID]; 2510 if (m_parts.ContainsKey(primID))
2511 {
2512 childPart = m_parts[primID];
2513 }
2485 } 2514 }
2515
2486 return childPart; 2516 return childPart;
2487 } 2517 }
2488 2518
@@ -2519,9 +2549,10 @@ namespace OpenSim.Region.Framework.Scenes
2519 /// <returns></returns> 2549 /// <returns></returns>
2520 public bool HasChildPrim(UUID primID) 2550 public bool HasChildPrim(UUID primID)
2521 { 2551 {
2522 if (m_parts.ContainsKey(primID)) 2552 lock (m_parts)
2523 { 2553 {
2524 return true; 2554 if (m_parts.ContainsKey(primID))
2555 return true;
2525 } 2556 }
2526 2557
2527 return false; 2558 return false;
@@ -3132,9 +3163,12 @@ namespace OpenSim.Region.Framework.Scenes
3132 public void UpdatePermissions(UUID AgentID, byte field, uint localID, 3163 public void UpdatePermissions(UUID AgentID, byte field, uint localID,
3133 uint mask, byte addRemTF) 3164 uint mask, byte addRemTF)
3134 { 3165 {
3135 foreach (SceneObjectPart part in m_parts.Values) 3166 List<SceneObjectPart> partList = null;
3136 part.UpdatePermissions(AgentID, field, localID, mask, 3167 lock (m_parts)
3137 addRemTF); 3168 partList = new List<SceneObjectPart>(m_parts.Values);
3169
3170 foreach (SceneObjectPart part in partList)
3171 part.UpdatePermissions(AgentID, field, localID, mask, addRemTF);
3138 3172
3139 HasGroupChanged = true; 3173 HasGroupChanged = true;
3140 } 3174 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 9e52b00..eefe8bb 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -4756,20 +4756,8 @@ namespace OpenSim.Region.Framework.Scenes
4756 if (ParentGroup == null || ParentGroup.IsDeleted) 4756 if (ParentGroup == null || ParentGroup.IsDeleted)
4757 return; 4757 return;
4758 4758
4759 Vector3 lPos = OffsetPosition; 4759 if (IsAttachment && ParentGroup.RootPart != this)
4760 4760 return;
4761 if (IsAttachment)
4762 {
4763 if (ParentGroup.RootPart != this)
4764 return;
4765
4766 lPos = ParentGroup.RootPart.AttachedPos;
4767 }
4768 else
4769 {
4770 if (ParentGroup.RootPart == this)
4771 lPos = AbsolutePosition;
4772 }
4773 4761
4774 // Causes this thread to dig into the Client Thread Data. 4762 // Causes this thread to dig into the Client Thread Data.
4775 // Remember your locking here! 4763 // Remember your locking here!
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 8b4f0ed..c5994b2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -37,6 +37,7 @@ using log4net;
37using OpenSim.Framework; 37using OpenSim.Framework;
38using OpenSim.Region.Framework.Interfaces; 38using OpenSim.Region.Framework.Interfaces;
39using OpenSim.Region.Framework.Scenes.Scripting; 39using OpenSim.Region.Framework.Scenes.Scripting;
40using OpenSim.Region.Framework.Scenes.Serialization;
40 41
41namespace OpenSim.Region.Framework.Scenes 42namespace OpenSim.Region.Framework.Scenes
42{ 43{
@@ -722,6 +723,70 @@ namespace OpenSim.Region.Framework.Scenes
722 return items; 723 return items;
723 } 724 }
724 725
726 public SceneObjectGroup GetRezReadySceneObject(TaskInventoryItem item)
727 {
728 AssetBase rezAsset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
729
730 if (null == rezAsset)
731 {
732 m_log.WarnFormat(
733 "[PRIM INVENTORY]: Could not find asset {0} for inventory item {1} in {2}",
734 item.AssetID, item.Name, m_part.Name);
735 return null;
736 }
737
738 string xmlData = Utils.BytesToString(rezAsset.Data);
739 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
740
741 group.ResetIDs();
742
743 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
744
745 // Since renaming the item in the inventory does not affect the name stored
746 // in the serialization, transfer the correct name from the inventory to the
747 // object itself before we rez.
748 rootPart.Name = item.Name;
749 rootPart.Description = item.Description;
750
751 List<SceneObjectPart> partList = null;
752
753 lock (group.Children)
754 partList = new List<SceneObjectPart>(group.Children.Values);
755
756 group.SetGroup(m_part.GroupID, null);
757
758 if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0)
759 {
760 if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions())
761 {
762 foreach (SceneObjectPart part in partList)
763 {
764 part.EveryoneMask = item.EveryonePermissions;
765 part.NextOwnerMask = item.NextPermissions;
766 }
767
768 group.ApplyNextOwnerPermissions();
769 }
770 }
771
772 foreach (SceneObjectPart part in partList)
773 {
774 if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0)
775 {
776 part.LastOwnerID = part.OwnerID;
777 part.OwnerID = item.OwnerID;
778 part.Inventory.ChangeInventoryOwner(item.OwnerID);
779 }
780
781 part.EveryoneMask = item.EveryonePermissions;
782 part.NextOwnerMask = item.NextPermissions;
783 }
784
785 rootPart.TrimPermissions();
786
787 return group;
788 }
789
725 /// <summary> 790 /// <summary>
726 /// Update an existing inventory item. 791 /// Update an existing inventory item.
727 /// </summary> 792 /// </summary>
@@ -1197,6 +1262,5 @@ namespace OpenSim.Region.Framework.Scenes
1197 1262
1198 Items.LockItemsForRead(false); 1263 Items.LockItemsForRead(false);
1199 } 1264 }
1200
1201 } 1265 }
1202} 1266} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 02e60f8..cd80eb0 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2668,15 +2668,15 @@ namespace OpenSim.Region.Framework.Scenes
2668 { 2668 {
2669 m_perfMonMS = Util.EnvironmentTickCount(); 2669 m_perfMonMS = Util.EnvironmentTickCount();
2670 2670
2671 PhysicsActor actor = m_physicsActor;
2672 Vector3 velocity = (actor != null) ? actor.Velocity : Vector3.Zero;
2673
2674 Vector3 pos = m_pos; 2671 Vector3 pos = m_pos;
2675 pos.Z += m_appearance.HipOffset; 2672 pos.Z += m_appearance.HipOffset;
2676 2673
2677 //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); 2674 //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
2678 2675
2679 remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity); 2676 remoteClient.SendPrimUpdate(
2677 this,
2678 PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity
2679 | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
2680 2680
2681 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2681 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2682 m_scene.StatsReporter.AddAgentUpdates(1); 2682 m_scene.StatsReporter.AddAgentUpdates(1);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
index fc66c85..3e2a2af 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/EntityManagerTests.cs
@@ -134,7 +134,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
134 sop.Text = RandomName(); 134 sop.Text = RandomName();
135 sop.SitName = RandomName(); 135 sop.SitName = RandomName();
136 sop.TouchName = RandomName(); 136 sop.TouchName = RandomName();
137 sop.ObjectFlags |= (uint)PrimFlags.Phantom; 137 sop.Flags |= PrimFlags.Phantom;
138 138
139 SceneObjectGroup sog = new SceneObjectGroup(sop); 139 SceneObjectGroup sog = new SceneObjectGroup(sop);
140 scene.AddNewSceneObject(sog, false); 140 scene.AddNewSceneObject(sog, false);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
new file mode 100644
index 0000000..da8199d
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -0,0 +1,143 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Text;
32using System.Threading;
33using System.Timers;
34using Timer=System.Timers.Timer;
35using Nini.Config;
36using NUnit.Framework;
37using NUnit.Framework.SyntaxHelpers;
38using OpenMetaverse;
39using OpenMetaverse.Assets;
40using OpenSim.Framework;
41using OpenSim.Framework.Communications;
42using OpenSim.Region.Framework.Scenes;
43using OpenSim.Region.Framework.Interfaces;
44using OpenSim.Region.CoreModules.Avatar.Inventory.Archiver;
45using OpenSim.Region.CoreModules.World.Serialiser;
46using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
47using OpenSim.Services.Interfaces;
48using OpenSim.Tests.Common;
49using OpenSim.Tests.Common.Mock;
50using OpenSim.Tests.Common.Setup;
51
52namespace OpenSim.Region.Framework.Tests
53{
54 [TestFixture]
55 public class TaskInventoryTests
56 {
57 protected UserAccount CreateUser(Scene scene)
58 {
59 string userFirstName = "Jock";
60 string userLastName = "Stirrup";
61 string userPassword = "troll";
62 UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020");
63 return UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword);
64 }
65
66 protected SceneObjectGroup CreateSO1(Scene scene, UUID ownerId)
67 {
68 string part1Name = "part1";
69 UUID part1Id = UUID.Parse("10000000-0000-0000-0000-000000000000");
70 SceneObjectPart part1
71 = new SceneObjectPart(ownerId, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
72 { Name = part1Name, UUID = part1Id };
73 return new SceneObjectGroup(part1);
74 }
75
76 protected TaskInventoryItem CreateSOItem1(Scene scene, SceneObjectPart part)
77 {
78 AssetNotecard nc = new AssetNotecard("Hello World!");
79 UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000");
80 UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000");
81 AssetBase ncAsset
82 = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero);
83 scene.AssetService.Store(ncAsset);
84 TaskInventoryItem ncItem
85 = new TaskInventoryItem
86 { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid,
87 Type = (int)AssetType.Notecard, InvType = (int)InventoryType.Notecard };
88 part.Inventory.AddInventoryItem(ncItem, true);
89
90 return ncItem;
91 }
92
93 /// <summary>
94 /// Test MoveTaskInventoryItem where the item has no parent folder assigned.
95 /// </summary>
96 /// This should place it in the most suitable user folder.
97 [Test]
98 public void TestMoveTaskInventoryItem()
99 {
100 TestHelper.InMethod();
101// log4net.Config.XmlConfigurator.Configure();
102
103 Scene scene = SceneSetupHelpers.SetupScene("inventory");
104 UserAccount user1 = CreateUser(scene);
105 SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID);
106 SceneObjectPart sop1 = sog1.RootPart;
107 TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1);
108 InventoryFolderBase folder
109 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0];
110
111 // Perform test
112 scene.MoveTaskInventoryItem(user1.PrincipalID, folder.ID, sop1, sopItem1.ItemID);
113
114 InventoryItemBase ncUserItem
115 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Objects/ncItem");
116 Assert.That(ncUserItem, Is.Not.Null, "Objects/ncItem was not found");
117 }
118
119 /// <summary>
120 /// Test MoveTaskInventoryItem where the item has no parent folder assigned.
121 /// </summary>
122 /// This should place it in the most suitable user folder.
123 [Test]
124 public void TestMoveTaskInventoryItemNoParent()
125 {
126 TestHelper.InMethod();
127// log4net.Config.XmlConfigurator.Configure();
128
129 Scene scene = SceneSetupHelpers.SetupScene("inventory");
130 UserAccount user1 = CreateUser(scene);
131 SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID);
132 SceneObjectPart sop1 = sog1.RootPart;
133 TaskInventoryItem sopItem1 = CreateSOItem1(scene, sop1);
134
135 // Perform test
136 scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID);
137
138 InventoryItemBase ncUserItem
139 = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Notecards/ncItem");
140 Assert.That(ncUserItem, Is.Not.Null, "Notecards/ncItem was not found");
141 }
142 }
143} \ No newline at end of file