aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs18
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs154
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs252
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs68
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs39
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs21
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs31
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs19
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs160
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs25
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs18
17 files changed, 620 insertions, 210 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
index 05fc2ad..305975e 100644
--- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs
@@ -38,7 +38,23 @@ namespace OpenSim.Region.Framework.Interfaces
38 public interface IInventoryAccessModule 38 public interface IInventoryAccessModule
39 { 39 {
40 UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data); 40 UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data);
41 UUID DeleteToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient); 41
42 /// <summary>
43 /// Copy objects to a user's inventory.
44 /// </summary>
45 /// <remarks>
46 /// Is it left to the caller to delete them from the scene if required.
47 /// </remarks>
48 /// <param name="action"></param>
49 /// <param name="folderID"></param>
50 /// <param name="objectGroups"></param>
51 /// <param name="remoteClient"></param>
52 /// <returns>
53 /// Returns the UUID of the newly created item asset (not the item itself).
54 /// FIXME: This is not very useful. It would be far more useful to return a list of items instead.
55 /// </returns>
56 UUID CopyToInventory(DeRezAction action, UUID folderID, List<SceneObjectGroup> objectGroups, IClientAPI remoteClient);
57
42 SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, 58 SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
43 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 59 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
44 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment); 60 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment);
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 23be9c2..14ecd44 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -223,7 +223,8 @@ namespace OpenSim.Region.Framework
223 catch (Exception e) 223 catch (Exception e)
224 { 224 {
225 m_log.ErrorFormat( 225 m_log.ErrorFormat(
226 "[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e); 226 "[MODULES]: Could not load types for plugin DLL {0}. Exception {1} {2}",
227 pluginAssembly.FullName, e.Message, e.StackTrace);
227 228
228 // justincc: Right now this is fatal to really get the user's attention 229 // justincc: Right now this is fatal to really get the user's attention
229 throw e; 230 throw e;
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 8feb022..3423542 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -143,7 +143,8 @@ namespace OpenSim.Region.Framework.Scenes
143 { 143 {
144 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 144 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
145 if (invAccess != null) 145 if (invAccess != null)
146 invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient); 146 invAccess.CopyToInventory(x.action, x.folderID, x.objectGroups, x.remoteClient);
147
147 if (x.permissionToDelete) 148 if (x.permissionToDelete)
148 { 149 {
149 foreach (SceneObjectGroup g in x.objectGroups) 150 foreach (SceneObjectGroup g in x.objectGroups)
diff --git a/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs b/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs
new file mode 100644
index 0000000..af8ccda
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/CoalescedSceneObjects.cs
@@ -0,0 +1,154 @@
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.Linq;
31using OpenMetaverse;
32
33namespace OpenSim.Region.Framework.Scenes
34{
35 /// <summary>
36 /// Represents a coalescene of scene objects. A coalescence occurs when objects that are not in the same linkset
37 /// are grouped together.
38 /// </summary>
39 public class CoalescedSceneObjects
40 {
41 /// <summary>
42 /// The creator of this coalesence, though not necessarily the objects within it.
43 /// </summary>
44 public UUID CreatorId { get; set; }
45
46 /// <summary>
47 /// The number of objects in this coalesence
48 /// </summary>
49 public int Count
50 {
51 get
52 {
53 lock (m_memberObjects)
54 return m_memberObjects.Count;
55 }
56 }
57
58 /// <summary>
59 /// Does this coalesence have any member objects?
60 /// </summary>
61 public bool HasObjects { get { return Count > 0; } }
62
63 /// <summary>
64 /// Get the objects currently in this coalescence
65 /// </summary>
66 public List<SceneObjectGroup> Objects
67 {
68 get
69 {
70 lock (m_memberObjects)
71 return new List<SceneObjectGroup>(m_memberObjects);
72 }
73 }
74
75 /// <summary>
76 /// Get the scene that contains the objects in this coalescence. If there are no objects then null is returned.
77 /// </summary>
78 public Scene Scene
79 {
80 get
81 {
82 if (!HasObjects)
83 return null;
84 else
85 return Objects[0].Scene;
86 }
87 }
88
89 /// <summary>
90 /// At this point, we need to preserve the order of objects added to the coalescence, since the first
91 /// one will end up matching the item name when rerezzed.
92 /// </summary>
93 protected List<SceneObjectGroup> m_memberObjects = new List<SceneObjectGroup>();
94
95 public CoalescedSceneObjects(UUID creatorId)
96 {
97 CreatorId = creatorId;
98 }
99
100 public CoalescedSceneObjects(UUID creatorId, params SceneObjectGroup[] objs) : this(creatorId)
101 {
102 foreach (SceneObjectGroup obj in objs)
103 Add(obj);
104 }
105
106 /// <summary>
107 /// Add an object to the coalescence.
108 /// </summary>
109 /// <param name="obj"></param>
110 /// <param name="offset">The offset of the object within the group</param>
111 public void Add(SceneObjectGroup obj)
112 {
113 lock (m_memberObjects)
114 m_memberObjects.Add(obj);
115 }
116
117 /// <summary>
118 /// Removes a scene object from the coalescene
119 /// </summary>
120 /// <param name="sceneObjectId"></param>
121 /// <returns>true if the object was there to be removed, false if not.</returns>
122 public bool Remove(SceneObjectGroup obj)
123 {
124 lock (m_memberObjects)
125 return m_memberObjects.Remove(obj);
126 }
127
128 /// <summary>
129 /// Get the total size of the coalescence (the size required to cover all the objects within it) and the
130 /// offsets of each of those objects.
131 /// </summary>
132 /// <param name="size"></param>
133 /// <returns>
134 /// An array of offsets. The order of objects is the same as returned from the Objects property
135 /// </returns>
136 public Vector3[] GetSizeAndOffsets(out Vector3 size)
137 {
138 float minX, minY, minZ;
139 float maxX, maxY, maxZ;
140
141 Vector3[] offsets
142 = Scene.GetCombinedBoundingBox(
143 Objects, out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
144
145 float sizeX = maxX - minX;
146 float sizeY = maxY - minY;
147 float sizeZ = maxZ - minZ;
148
149 size = new Vector3(sizeX, sizeY, sizeZ);
150
151 return offsets;
152 }
153 }
154} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index f9599f5..e3ed905 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -58,17 +58,8 @@ namespace OpenSim.Region.Framework.Scenes
58 58
59 public class Prioritizer 59 public class Prioritizer
60 { 60 {
61// private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); 61 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
62 62
63 /// <summary>
64 /// This is added to the priority of all child prims, to make sure that the root prim update is sent to the
65 /// viewer before child prim updates.
66 /// The adjustment is added to child prims and subtracted from root prims, so the gap ends up
67 /// being double. We do it both ways so that there is a still a priority delta even if the priority is already
68 /// double.MinValue or double.MaxValue.
69 /// </summary>
70 private double m_childPrimAdjustmentFactor = 0.05;
71
72 private Scene m_scene; 63 private Scene m_scene;
73 64
74 public Prioritizer(Scene scene) 65 public Prioritizer(Scene scene)
@@ -76,17 +67,35 @@ namespace OpenSim.Region.Framework.Scenes
76 m_scene = scene; 67 m_scene = scene;
77 } 68 }
78 69
79 public double GetUpdatePriority(IClientAPI client, ISceneEntity entity) 70 /// <summary>
71 /// Returns the priority queue into which the update should be placed. Updates within a
72 /// queue will be processed in arrival order. There are currently 12 priority queues
73 /// implemented in PriorityQueue class in LLClientView. Queue 0 is generally retained
74 /// for avatar updates. The fair queuing discipline for processing the priority queues
75 /// assumes that the number of entities in each priority queues increases exponentially.
76 /// So for example... if queue 1 contains all updates within 10m of the avatar or camera
77 /// then queue 2 at 20m is about 3X bigger in space & about 3X bigger in total number
78 /// of updates.
79 /// </summary>
80 public uint GetUpdatePriority(IClientAPI client, ISceneEntity entity)
80 { 81 {
81 double priority = 0; 82 // If entity is null we have a serious problem
82
83 if (entity == null) 83 if (entity == null)
84 return 100000; 84 {
85 m_log.WarnFormat("[PRIORITIZER] attempt to prioritize null entity");
86 throw new InvalidOperationException("Prioritization entity not defined");
87 }
88
89 // If this is an update for our own avatar give it the highest priority
90 if (client.AgentId == entity.UUID)
91 return 0;
92
93 uint priority;
85 94
86 switch (m_scene.UpdatePrioritizationScheme) 95 switch (m_scene.UpdatePrioritizationScheme)
87 { 96 {
88 case UpdatePrioritizationSchemes.Time: 97 case UpdatePrioritizationSchemes.Time:
89 priority = GetPriorityByTime(); 98 priority = GetPriorityByTime(client, entity);
90 break; 99 break;
91 case UpdatePrioritizationSchemes.Distance: 100 case UpdatePrioritizationSchemes.Distance:
92 priority = GetPriorityByDistance(client, entity); 101 priority = GetPriorityByDistance(client, entity);
@@ -104,180 +113,115 @@ namespace OpenSim.Region.Framework.Scenes
104 throw new InvalidOperationException("UpdatePrioritizationScheme not defined."); 113 throw new InvalidOperationException("UpdatePrioritizationScheme not defined.");
105 } 114 }
106 115
107 // Adjust priority so that root prims are sent to the viewer first. This is especially important for
108 // attachments acting as huds, since current viewers fail to display hud child prims if their updates
109 // arrive before the root one.
110 if (entity is SceneObjectPart)
111 {
112 SceneObjectPart sop = ((SceneObjectPart)entity);
113
114 if (sop.IsRoot)
115 {
116 if (priority >= double.MinValue + m_childPrimAdjustmentFactor)
117 priority -= m_childPrimAdjustmentFactor;
118 }
119 else
120 {
121 if (priority <= double.MaxValue - m_childPrimAdjustmentFactor)
122 priority += m_childPrimAdjustmentFactor;
123 }
124 }
125
126 return priority; 116 return priority;
127 } 117 }
128 118
129 private double GetPriorityByTime() 119
120 private uint GetPriorityByTime(IClientAPI client, ISceneEntity entity)
130 { 121 {
131 return DateTime.UtcNow.ToOADate(); 122 return 1;
132 } 123 }
133 124
134 private double GetPriorityByDistance(IClientAPI client, ISceneEntity entity) 125 private uint GetPriorityByDistance(IClientAPI client, ISceneEntity entity)
135 { 126 {
136 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 127 return ComputeDistancePriority(client,entity,false);
137 if (presence != null) 128 }
138 { 129
139 // If this is an update for our own avatar give it the highest priority 130 private uint GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
140 if (presence == entity) 131 {
141 return 0.0; 132 return ComputeDistancePriority(client,entity,true);
142
143 // Use the camera position for local agents and avatar position for remote agents
144 Vector3 presencePos = (presence.IsChildAgent) ?
145 presence.AbsolutePosition :
146 presence.CameraPosition;
147
148 // Use group position for child prims
149 Vector3 entityPos;
150 if (entity is SceneObjectPart)
151 {
152 // Can't use Scene.GetGroupByPrim() here, since the entity may have been delete from the scene
153 // before its scheduled update was triggered
154 //entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
155 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
156 }
157 else
158 {
159 entityPos = entity.AbsolutePosition;
160 }
161
162 return Vector3.DistanceSquared(presencePos, entityPos);
163 }
164
165 return double.NaN;
166 } 133 }
167 134
168 private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) 135 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
169 { 136 {
137 uint pqueue = ComputeDistancePriority(client,entity,true);
138
170 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 139 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
171 if (presence != null) 140 if (presence != null)
172 { 141 {
173 // If this is an update for our own avatar give it the highest priority
174 if (presence == entity)
175 return 0.0;
176
177 // Use group position for child prims
178 Vector3 entityPos = entity.AbsolutePosition;
179 if (entity is SceneObjectPart)
180 {
181 // Can't use Scene.GetGroupByPrim() here, since the entity may have been delete from the scene
182 // before its scheduled update was triggered
183 //entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition;
184 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
185 }
186 else
187 {
188 entityPos = entity.AbsolutePosition;
189 }
190
191 if (!presence.IsChildAgent) 142 if (!presence.IsChildAgent)
192 { 143 {
193 // Root agent. Use distance from camera and a priority decrease for objects behind us 144 if (entity is SceneObjectPart)
194 Vector3 camPosition = presence.CameraPosition; 145 {
195 Vector3 camAtAxis = presence.CameraAtAxis; 146 // Non physical prims are lower priority than physical prims
196 147 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
197 // Distance 148 if (physActor == null || !physActor.IsPhysical)
198 double priority = Vector3.DistanceSquared(camPosition, entityPos); 149 pqueue++;
199
200 // Plane equation
201 float d = -Vector3.Dot(camPosition, camAtAxis);
202 float p = Vector3.Dot(camAtAxis, entityPos) + d;
203 if (p < 0.0f) priority *= 2.0;
204
205 return priority;
206 }
207 else
208 {
209 // Child agent. Use the normal distance method
210 Vector3 presencePos = presence.AbsolutePosition;
211 150
212 return Vector3.DistanceSquared(presencePos, entityPos); 151 // Attachments are high priority,
152 // MIC: shouldn't these already be in the highest priority queue already
153 // since their root position is same as the avatars?
154 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
155 pqueue = 1;
156 }
213 } 157 }
214 } 158 }
215 159
216 return double.NaN; 160 return pqueue;
217 } 161 }
218 162
219 private double GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 163 private uint ComputeDistancePriority(IClientAPI client, ISceneEntity entity, bool useFrontBack)
220 { 164 {
221 // If this is an update for our own avatar give it the highest priority 165 // Get this agent's position
222 if (client.AgentId == entity.UUID) 166 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
223 return 0.0; 167 if (presence == null)
224 if (entity == null) 168 {
225 return double.NaN; 169 // this shouldn't happen, it basically means that we are prioritizing
170 // updates to send to a client that doesn't have a presence in the scene
171 // seems like there's race condition here...
226 172
227 // Use group position for child prims 173 // m_log.WarnFormat("[PRIORITIZER] attempt to use agent {0} not in the scene",client.AgentId);
174 // throw new InvalidOperationException("Prioritization agent not defined");
175 return Int32.MaxValue;
176 }
177
178 // Use group position for child prims, since we are putting child prims in
179 // the same queue with the root of the group, the root prim (which goes into
180 // the queue first) should always be sent first, no need to adjust child prim
181 // priorities
228 Vector3 entityPos = entity.AbsolutePosition; 182 Vector3 entityPos = entity.AbsolutePosition;
229 if (entity is SceneObjectPart) 183 if (entity is SceneObjectPart)
230 { 184 {
231 SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup; 185 SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup;
232 if (group != null) 186 if (group != null)
233 entityPos = group.AbsolutePosition; 187 entityPos = group.AbsolutePosition;
234 else
235 entityPos = entity.AbsolutePosition;
236 } 188 }
237 else
238 entityPos = entity.AbsolutePosition;
239 189
240 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 190 // Use the camera position for local agents and avatar position for remote agents
241 if (presence != null) 191 Vector3 presencePos = (presence.IsChildAgent) ?
242 { 192 presence.AbsolutePosition :
243 if (!presence.IsChildAgent) 193 presence.CameraPosition;
244 {
245 if (entity is ScenePresence)
246 return 1.0;
247
248 // Root agent. Use distance from camera and a priority decrease for objects behind us
249 Vector3 camPosition = presence.CameraPosition;
250 Vector3 camAtAxis = presence.CameraAtAxis;
251 194
252 // Distance 195 // Compute the distance...
253 double priority = Vector3.DistanceSquared(camPosition, entityPos); 196 double distance = Vector3.Distance(presencePos, entityPos);
254 197
255 // Plane equation 198 // And convert the distance to a priority queue, this computation gives queues
256 float d = -Vector3.Dot(camPosition, camAtAxis); 199 // at 10, 20, 40, 80, 160, 320, 640, and 1280m
257 float p = Vector3.Dot(camAtAxis, entityPos) + d; 200 uint pqueue = 1;
258 if (p < 0.0f) priority *= 2.0; 201 for (int i = 0; i < 8; i++)
259 202 {
260 if (entity is SceneObjectPart) 203 if (distance < 10 * Math.Pow(2.0,i))
261 { 204 break;
262 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; 205 pqueue++;
263 if (physActor == null || !physActor.IsPhysical) 206 }
264 priority += 100; 207
265 208 // If this is a root agent, then determine front & back
266 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) 209 // Bump up the priority queue (drop the priority) for any objects behind the avatar
267 priority = 1.0; 210 if (useFrontBack && ! presence.IsChildAgent)
268 } 211 {
269 return priority; 212 // Root agent, decrease priority for objects behind us
270 } 213 Vector3 camPosition = presence.CameraPosition;
271 else 214 Vector3 camAtAxis = presence.CameraAtAxis;
272 { 215
273 // Child agent. Use the normal distance method 216 // Plane equation
274 Vector3 presencePos = presence.AbsolutePosition; 217 float d = -Vector3.Dot(camPosition, camAtAxis);
275 218 float p = Vector3.Dot(camAtAxis, entityPos) + d;
276 return Vector3.DistanceSquared(presencePos, entityPos); 219 if (p < 0.0f)
277 } 220 pqueue++;
278 } 221 }
279 222
280 return double.NaN; 223 return pqueue;
281 } 224 }
225
282 } 226 }
283} 227}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 73dd531..0f85925 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -1955,11 +1955,49 @@ namespace OpenSim.Region.Framework.Scenes
1955 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 1955 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
1956 bool RezSelected, bool RemoveItem, UUID fromTaskID) 1956 bool RezSelected, bool RemoveItem, UUID fromTaskID)
1957 { 1957 {
1958 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>(); 1958// m_log.DebugFormat(
1959 if (invAccess != null) 1959// "[PRIM INVENTORY]: RezObject from {0} for item {1} from task id {2}",
1960 invAccess.RezObject( 1960// remoteClient.Name, itemID, fromTaskID);
1961 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 1961
1962 RezSelected, RemoveItem, fromTaskID, false); 1962 if (fromTaskID == UUID.Zero)
1963 {
1964 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
1965 if (invAccess != null)
1966 invAccess.RezObject(
1967 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
1968 RezSelected, RemoveItem, fromTaskID, false);
1969 }
1970 else
1971 {
1972 SceneObjectPart part = GetSceneObjectPart(fromTaskID);
1973 if (part == null)
1974 {
1975 m_log.ErrorFormat(
1976 "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such scene object",
1977 remoteClient.Name, itemID, fromTaskID);
1978
1979 return;
1980 }
1981
1982 TaskInventoryItem item = part.Inventory.GetInventoryItem(itemID);
1983 if (item == null)
1984 {
1985 m_log.ErrorFormat(
1986 "[TASK INVENTORY]: {0} tried to rez item id {1} from object id {2} but there is no such item",
1987 remoteClient.Name, itemID, fromTaskID);
1988
1989 return;
1990 }
1991
1992 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
1993 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
1994 Vector3 pos
1995 = GetNewRezLocation(
1996 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
1997 BypassRayCast, bRayEndIsIntersection, true, scale, false);
1998
1999 RezObject(part, item, pos, null, Vector3.Zero, 0);
2000 }
1963 } 2001 }
1964 2002
1965 /// <summary> 2003 /// <summary>
@@ -1967,14 +2005,14 @@ namespace OpenSim.Region.Framework.Scenes
1967 /// </summary> 2005 /// </summary>
1968 /// <param name="sourcePart"></param> 2006 /// <param name="sourcePart"></param>
1969 /// <param name="item"></param> 2007 /// <param name="item"></param>
1970 /// <param name="pos"></param> 2008 /// <param name="pos">The position of the rezzed object.</param>
1971 /// <param name="rot"></param> 2009 /// <param name="rot">The rotation of the rezzed object. If null, then the rotation stored with the object
1972 /// <param name="vel"></param> 2010 /// will be used if it exists.</param>
2011 /// <param name="vel">The velocity of the rezzed object.</param>
1973 /// <param name="param"></param> 2012 /// <param name="param"></param>
1974 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns> 2013 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful</returns>
1975 public virtual SceneObjectGroup RezObject( 2014 public virtual SceneObjectGroup RezObject(
1976 SceneObjectPart sourcePart, TaskInventoryItem item, 2015 SceneObjectPart sourcePart, TaskInventoryItem item, Vector3 pos, Quaternion? rot, Vector3 vel, int param)
1977 Vector3 pos, Quaternion rot, Vector3 vel, int param)
1978 { 2016 {
1979 if (null == item) 2017 if (null == item)
1980 return null; 2018 return null;
@@ -1992,8 +2030,14 @@ namespace OpenSim.Region.Framework.Scenes
1992 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) 2030 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1993 sourcePart.Inventory.RemoveInventoryItem(item.ItemID); 2031 sourcePart.Inventory.RemoveInventoryItem(item.ItemID);
1994 } 2032 }
1995 2033
1996 AddNewSceneObject(group, true, pos, rot, vel); 2034 AddNewSceneObject(group, true);
2035
2036 group.AbsolutePosition = pos;
2037 group.Velocity = vel;
2038
2039 if (rot != null)
2040 group.UpdateGroupRotationR((Quaternion)rot);
1997 2041
1998 // We can only call this after adding the scene object, since the scene object references the scene 2042 // We can only call this after adding the scene object, since the scene object references the scene
1999 // to find out if scripts should be activated at all. 2043 // to find out if scripts should be activated at all.
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index f0acc38..01de824 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -3665,6 +3665,15 @@ namespace OpenSim.Region.Framework.Scenes
3665 return false; 3665 return false;
3666 } 3666 }
3667 3667
3668 int num = m_sceneGraph.GetNumberOfScenePresences();
3669
3670 if (num >= RegionInfo.RegionSettings.AgentLimit)
3671 {
3672 if (!Permissions.IsAdministrator(cAgentData.AgentID))
3673 return false;
3674 }
3675
3676
3668 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3677 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3669 3678
3670 if (childAgentUpdate != null) 3679 if (childAgentUpdate != null)
@@ -4839,7 +4848,20 @@ namespace OpenSim.Region.Framework.Scenes
4839 } 4848 }
4840 } 4849 }
4841 4850
4842 public Vector3[] GetCombinedBoundingBox(List<SceneObjectGroup> objects, out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 4851 /// <summary>
4852 /// Get the volume of space that will encompass all the given objects.
4853 /// </summary>
4854 /// <param name="objects"></param>
4855 /// <param name="minX"></param>
4856 /// <param name="maxX"></param>
4857 /// <param name="minY"></param>
4858 /// <param name="maxY"></param>
4859 /// <param name="minZ"></param>
4860 /// <param name="maxZ"></param>
4861 /// <returns></returns>
4862 public static Vector3[] GetCombinedBoundingBox(
4863 List<SceneObjectGroup> objects,
4864 out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
4843 { 4865 {
4844 minX = 256; 4866 minX = 256;
4845 maxX = -256; 4867 maxX = -256;
@@ -4857,6 +4879,10 @@ namespace OpenSim.Region.Framework.Scenes
4857 Vector3 vec = g.AbsolutePosition; 4879 Vector3 vec = g.AbsolutePosition;
4858 4880
4859 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 4881 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
4882
4883// m_log.DebugFormat(
4884// "[SCENE]: For {0} found AxisAlignedBoundingBoxRaw {1}, {2}",
4885// g.Name, new Vector3(ominX, ominY, ominZ), new Vector3(omaxX, omaxY, omaxZ));
4860 4886
4861 ominX += vec.X; 4887 ominX += vec.X;
4862 omaxX += vec.X; 4888 omaxX += vec.X;
@@ -4949,6 +4975,17 @@ namespace OpenSim.Region.Framework.Scenes
4949 // child agent creation, thereby emulating the SL behavior. 4975 // child agent creation, thereby emulating the SL behavior.
4950 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 4976 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
4951 { 4977 {
4978 int num = m_sceneGraph.GetNumberOfScenePresences();
4979
4980 if (num >= RegionInfo.RegionSettings.AgentLimit)
4981 {
4982 if (!Permissions.IsAdministrator(agentID))
4983 {
4984 reason = "The region is full";
4985 return false;
4986 }
4987 }
4988
4952 reason = String.Empty; 4989 reason = String.Empty;
4953 return true; 4990 return true;
4954 } 4991 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 97af0a0..fc31b65 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -800,6 +800,11 @@ namespace OpenSim.Region.Framework.Scenes
800 return m_scenePresenceArray; 800 return m_scenePresenceArray;
801 } 801 }
802 802
803 public int GetNumberOfScenePresences()
804 {
805 return m_scenePresenceArray.Count;
806 }
807
803 /// <summary> 808 /// <summary>
804 /// Request a scene presence by UUID. Fast, indexed lookup. 809 /// Request a scene presence by UUID. Fast, indexed lookup.
805 /// </summary> 810 /// </summary>
@@ -997,6 +1002,8 @@ namespace OpenSim.Region.Framework.Scenes
997 { 1002 {
998 foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts) 1003 foreach (SceneObjectPart p in ((SceneObjectGroup)entity).Parts)
999 { 1004 {
1005// m_log.DebugFormat("[SCENE GRAPH]: Part {0} has name {1}", p.UUID, p.Name);
1006
1000 if (p.Name == name) 1007 if (p.Name == name)
1001 { 1008 {
1002 sop = p; 1009 sop = p;
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index e8095c0..4bca3d0 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -81,16 +81,20 @@ namespace OpenSim.Region.Framework.Scenes
81 } 81 }
82 82
83 /// <summary> 83 /// <summary>
84 /// Add an inventory item to a prim in this group. 84 /// Add an inventory item from a user's inventory to a prim in this scene object.
85 /// </summary> 85 /// </summary>
86 /// <param name="remoteClient"></param> 86 /// <param name="remoteClient">The client adding the item.</param>
87 /// <param name="localID"></param> 87 /// <param name="localID">The local ID of the part receiving the add.</param>
88 /// <param name="item"></param> 88 /// <param name="item">The user inventory item being added.</param>
89 /// <param name="copyItemID">The item UUID that should be used by the new item.</param> 89 /// <param name="copyItemID">The item UUID that should be used by the new item.</param>
90 /// <returns></returns> 90 /// <returns></returns>
91 public bool AddInventoryItem(IClientAPI remoteClient, uint localID, 91 public bool AddInventoryItem(IClientAPI remoteClient, uint localID,
92 InventoryItemBase item, UUID copyItemID) 92 InventoryItemBase item, UUID copyItemID)
93 { 93 {
94// m_log.DebugFormat(
95// "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}",
96// item.Name, remoteClient.Name, localID);
97
94 UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID; 98 UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID;
95 99
96 SceneObjectPart part = GetChildPart(localID); 100 SceneObjectPart part = GetChildPart(localID);
@@ -132,15 +136,20 @@ namespace OpenSim.Region.Framework.Scenes
132 taskItem.GroupPermissions = item.GroupPermissions; 136 taskItem.GroupPermissions = item.GroupPermissions;
133 taskItem.NextPermissions = item.NextPermissions; 137 taskItem.NextPermissions = item.NextPermissions;
134 } 138 }
135 139
136 taskItem.Flags = item.Flags; 140 taskItem.Flags = item.Flags;
141
142// m_log.DebugFormat(
143// "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}",
144// taskItem.Flags, taskItem.Name, localID, remoteClient.Name);
145
137 // TODO: These are pending addition of those fields to TaskInventoryItem 146 // TODO: These are pending addition of those fields to TaskInventoryItem
138// taskItem.SalePrice = item.SalePrice; 147// taskItem.SalePrice = item.SalePrice;
139// taskItem.SaleType = item.SaleType; 148// taskItem.SaleType = item.SaleType;
140 taskItem.CreationDate = (uint)item.CreationDate; 149 taskItem.CreationDate = (uint)item.CreationDate;
141 150
142 bool addFromAllowedDrop = false; 151 bool addFromAllowedDrop = false;
143 if (remoteClient!=null) 152 if (remoteClient != null)
144 { 153 {
145 addFromAllowedDrop = remoteClient.AgentId != part.OwnerID; 154 addFromAllowedDrop = remoteClient.AgentId != part.OwnerID;
146 } 155 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index ca7d9d9..19a9506 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -296,11 +296,14 @@ namespace OpenSim.Region.Framework.Scenes
296 { 296 {
297 Vector3 val = value; 297 Vector3 val = value;
298 298
299 if ((m_scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || m_scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 299 if (Scene != null)
300 || m_scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || m_scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
301 && !IsAttachmentCheckFull() && (!m_scene.LoadingPrims))
302 { 300 {
303 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 301 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
302 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
303 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
304 {
305 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
306 }
304 } 307 }
305 308
306 if (RootPart.GetStatusSandbox()) 309 if (RootPart.GetStatusSandbox())
@@ -308,8 +311,11 @@ namespace OpenSim.Region.Framework.Scenes
308 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 311 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
309 { 312 {
310 RootPart.ScriptSetPhysicsStatus(false); 313 RootPart.ScriptSetPhysicsStatus(false);
311 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"), 314
312 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false); 315 if (Scene != null)
316 Scene.SimChat(Utils.StringToBytes("Hit Sandbox Limit"),
317 ChatTypeEnum.DebugChannel, 0x7FFFFFFF, RootPart.AbsolutePosition, Name, UUID, false);
318
313 return; 319 return;
314 } 320 }
315 } 321 }
@@ -326,7 +332,8 @@ namespace OpenSim.Region.Framework.Scenes
326 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor); 332 //m_scene.PhysicsScene.AddPhysicsActorTaint(m_rootPart.PhysActor);
327 //} 333 //}
328 334
329 m_scene.EventManager.TriggerParcelPrimCountTainted(); 335 if (Scene != null)
336 Scene.EventManager.TriggerParcelPrimCountTainted();
330 } 337 }
331 } 338 }
332 339
@@ -1765,10 +1772,12 @@ namespace OpenSim.Region.Framework.Scenes
1765 /// <param name="part"></param> 1772 /// <param name="part"></param>
1766 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags) 1773 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags)
1767 { 1774 {
1768 remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask, 1775 remoteClient.SendObjectPropertiesFamilyData(RootPart, RequestFlags);
1769 RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask, 1776
1770 RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category, 1777// remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask,
1771 RootPart.CreatorID, RootPart.Name, RootPart.Description); 1778// RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask,
1779// RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category,
1780// RootPart.CreatorID, RootPart.Name, RootPart.Description);
1772 } 1781 }
1773 1782
1774 public void SetPartOwner(SceneObjectPart part, UUID cAgentID, UUID cGroupID) 1783 public void SetPartOwner(SceneObjectPart part, UUID cAgentID, UUID cGroupID)
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 4d5eedf..8a8a699 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -2055,15 +2055,7 @@ namespace OpenSim.Region.Framework.Scenes
2055 2055
2056 public void GetProperties(IClientAPI client) 2056 public void GetProperties(IClientAPI client)
2057 { 2057 {
2058 //Viewer wants date in microseconds so multiply it by 1,000,000. 2058 client.SendObjectPropertiesReply(this);
2059 client.SendObjectPropertiesReply(
2060 m_fromUserInventoryItemID, (ulong)_creationDate*(ulong)1e6, _creatorID, UUID.Zero, UUID.Zero,
2061 _groupID, (short)InventorySerial, _lastOwnerID, UUID, _ownerID,
2062 ParentGroup.RootPart.TouchName, new byte[0], ParentGroup.RootPart.SitName, Name, Description,
2063 ParentGroup.RootPart._ownerMask, ParentGroup.RootPart._nextOwnerMask, ParentGroup.RootPart._groupMask, ParentGroup.RootPart._everyoneMask,
2064 ParentGroup.RootPart._baseMask,
2065 ParentGroup.RootPart.ObjectSaleType,
2066 ParentGroup.RootPart.SalePrice);
2067 } 2059 }
2068 2060
2069 public UUID GetRootPartUUID() 2061 public UUID GetRootPartUUID()
@@ -2088,7 +2080,14 @@ namespace OpenSim.Region.Framework.Scenes
2088 2080
2089 axPos *= parentRot; 2081 axPos *= parentRot;
2090 Vector3 translationOffsetPosition = axPos; 2082 Vector3 translationOffsetPosition = axPos;
2091 return GroupPosition + translationOffsetPosition; 2083
2084// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name);
2085
2086 Vector3 worldPos = GroupPosition + translationOffsetPosition;
2087
2088// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name);
2089
2090 return worldPos;
2092 } 2091 }
2093 2092
2094 /// <summary> 2093 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs
new file mode 100644
index 0000000..55455cc
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs
@@ -0,0 +1,160 @@
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.Drawing;
31using System.IO;
32using System.Reflection;
33using System.Xml;
34using log4net;
35using OpenMetaverse;
36using OpenSim.Framework;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Region.Framework.Scenes;
39
40namespace OpenSim.Region.Framework.Scenes.Serialization
41{
42 /// <summary>
43 /// Serialize and deserialize coalesced scene objects.
44 /// </summary>
45 /// <remarks>
46 /// Deserialization not yet here.
47 /// </remarks>
48 public class CoalescedSceneObjectsSerializer
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 /// <summary>
53 /// Serialize coalesced objects to Xml
54 /// </summary>
55 /// <param name="coa"></param>
56 /// <returns></returns>
57 public static string ToXml(CoalescedSceneObjects coa)
58 {
59 using (StringWriter sw = new StringWriter())
60 {
61 using (XmlTextWriter writer = new XmlTextWriter(sw))
62 {
63 Vector3 size;
64
65 List<SceneObjectGroup> coaObjects = coa.Objects;
66
67// m_log.DebugFormat(
68// "[COALESCED SCENE OBJECTS SERIALIZER]: Writing {0} objects for coalesced object",
69// coaObjects.Count);
70
71 // This is weak - we're relying on the set of coalesced objects still being identical
72 Vector3[] offsets = coa.GetSizeAndOffsets(out size);
73
74 writer.WriteStartElement("CoalescedObject");
75
76 writer.WriteAttributeString("x", size.X.ToString());
77 writer.WriteAttributeString("y", size.Y.ToString());
78 writer.WriteAttributeString("z", size.Z.ToString());
79
80 // Embed the offsets into the group XML
81 for (int i = 0; i < coaObjects.Count; i++)
82 {
83 SceneObjectGroup obj = coaObjects[i];
84
85// m_log.DebugFormat(
86// "[COALESCED SCENE OBJECTS SERIALIZER]: Writing offset for object {0}, {1}",
87// i, obj.Name);
88
89 writer.WriteStartElement("SceneObjectGroup");
90 writer.WriteAttributeString("offsetx", offsets[i].X.ToString());
91 writer.WriteAttributeString("offsety", offsets[i].Y.ToString());
92 writer.WriteAttributeString("offsetz", offsets[i].Z.ToString());
93
94 SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, true);
95
96 writer.WriteEndElement(); // SceneObjectGroup
97 }
98
99 writer.WriteEndElement(); // CoalescedObject
100 }
101
102 string output = sw.ToString();
103
104// Console.WriteLine(output);
105
106 return output;
107 }
108 }
109
110 public static bool TryFromXml(string xml, out CoalescedSceneObjects coa)
111 {
112// m_log.DebugFormat("[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() deserializing {0}", xml);
113
114 coa = null;
115
116 using (StringReader sr = new StringReader(xml))
117 {
118 using (XmlTextReader reader = new XmlTextReader(sr))
119 {
120 try
121 {
122 reader.Read();
123 if (reader.Name != "CoalescedObject")
124 {
125 // m_log.DebugFormat(
126 // "[COALESCED SCENE OBJECTS SERIALIZER]: TryFromXml() root element was {0} so returning false",
127 // reader.Name);
128
129 return false;
130 }
131
132 coa = new CoalescedSceneObjects(UUID.Zero);
133 reader.Read();
134
135 while (reader.NodeType != XmlNodeType.EndElement && reader.Name != "CoalescedObject")
136 {
137 if (reader.Name == "SceneObjectGroup")
138 {
139 string soXml = reader.ReadOuterXml();
140 coa.Add(SceneObjectSerializer.FromOriginalXmlFormat(soXml));
141 }
142 }
143
144 reader.ReadEndElement(); // CoalescedObject
145 }
146 catch (Exception e)
147 {
148 m_log.ErrorFormat(
149 "[COALESCED SCENE OBJECTS SERIALIZER]: Deserialization of xml failed with {0} {1}",
150 e.Message, e.StackTrace);
151
152 return false;
153 }
154 }
155 }
156
157 return true;
158 }
159 }
160} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 57ae4fd..bb8a83a 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -139,6 +139,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
139 return sw.ToString(); 139 return sw.ToString();
140 } 140 }
141 } 141 }
142
142 143
143 /// <summary> 144 /// <summary>
144 /// Serialize a scene object to the original xml format 145 /// Serialize a scene object to the original xml format
@@ -147,10 +148,24 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
147 /// <returns></returns> 148 /// <returns></returns>
148 public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer) 149 public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer)
149 { 150 {
151 ToOriginalXmlFormat(sceneObject, writer, false);
152 }
153
154 /// <summary>
155 /// Serialize a scene object to the original xml format
156 /// </summary>
157 /// <param name="sceneObject"></param>
158 /// <param name="writer"></param>
159 /// <param name="noRootElement">If false, don't write the enclosing SceneObjectGroup element</param>
160 /// <returns></returns>
161 public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer, bool noRootElement)
162 {
150 //m_log.DebugFormat("[SERIALIZER]: Starting serialization of {0}", Name); 163 //m_log.DebugFormat("[SERIALIZER]: Starting serialization of {0}", Name);
151 //int time = System.Environment.TickCount; 164 //int time = System.Environment.TickCount;
152 165
153 writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty); 166 if (!noRootElement)
167 writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
168
154 writer.WriteStartElement(String.Empty, "RootPart", String.Empty); 169 writer.WriteStartElement(String.Empty, "RootPart", String.Empty);
155 ToXmlFormat(sceneObject.RootPart, writer); 170 ToXmlFormat(sceneObject.RootPart, writer);
156 writer.WriteEndElement(); 171 writer.WriteEndElement();
@@ -170,10 +185,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
170 185
171 writer.WriteEndElement(); // OtherParts 186 writer.WriteEndElement(); // OtherParts
172 sceneObject.SaveScriptedState(writer); 187 sceneObject.SaveScriptedState(writer);
173 writer.WriteEndElement(); // SceneObjectGroup 188
189 if (!noRootElement)
190 writer.WriteEndElement(); // SceneObjectGroup
174 191
175 //m_log.DebugFormat("[SERIALIZER]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time); 192 //m_log.DebugFormat("[SERIALIZER]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
176 } 193 }
177 194
178 protected static void ToXmlFormat(SceneObjectPart part, XmlTextWriter writer) 195 protected static void ToXmlFormat(SceneObjectPart part, XmlTextWriter writer)
179 { 196 {
@@ -1318,7 +1335,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1318 writer.WriteStartElement("SculptData"); 1335 writer.WriteStartElement("SculptData");
1319 byte[] sd; 1336 byte[] sd;
1320 if (shp.SculptData != null) 1337 if (shp.SculptData != null)
1321 sd = shp.ExtraParams; 1338 sd = shp.SculptData;
1322 else 1339 else
1323 sd = Utils.EmptyBytes; 1340 sd = Utils.EmptyBytes;
1324 writer.WriteBase64(sd, 0, sd.Length); 1341 writer.WriteBase64(sd, 0, sd.Length);
diff --git a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs
index 8588f7f..dd28416 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/StandaloneTeleportTests.cs
@@ -117,11 +117,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests
117 ISharedRegionModule interregionComms = new LocalSimulationConnectorModule(); 117 ISharedRegionModule interregionComms = new LocalSimulationConnectorModule();
118 118
119 119
120 Scene sceneB = SceneSetupHelpers.SetupScene("sceneB", sceneBId, 1010, 1010, "grid"); 120 Scene sceneB = SceneSetupHelpers.SetupScene("sceneB", sceneBId, 1010, 1010);
121 SceneSetupHelpers.SetupSceneModules(sceneB, new IniConfigSource(), interregionComms); 121 SceneSetupHelpers.SetupSceneModules(sceneB, new IniConfigSource(), interregionComms);
122 sceneB.RegisterRegionWithGrid(); 122 sceneB.RegisterRegionWithGrid();
123 123
124 Scene sceneA = SceneSetupHelpers.SetupScene("sceneA", sceneAId, 1000, 1000, "grid"); 124 Scene sceneA = SceneSetupHelpers.SetupScene("sceneA", sceneAId, 1000, 1000);
125 SceneSetupHelpers.SetupSceneModules(sceneA, new IniConfigSource(), interregionComms); 125 SceneSetupHelpers.SetupSceneModules(sceneA, new IniConfigSource(), interregionComms);
126 sceneA.RegisterRegionWithGrid(); 126 sceneA.RegisterRegionWithGrid();
127 127
diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
index 8138bcc..2aef4b0 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs
@@ -101,7 +101,7 @@ namespace OpenSim.Region.Framework.Tests
101 TestHelper.InMethod(); 101 TestHelper.InMethod();
102// log4net.Config.XmlConfigurator.Configure(); 102// log4net.Config.XmlConfigurator.Configure();
103 103
104 Scene scene = SceneSetupHelpers.SetupScene("inventory"); 104 Scene scene = SceneSetupHelpers.SetupScene();
105 UserAccount user1 = CreateUser(scene); 105 UserAccount user1 = CreateUser(scene);
106 SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); 106 SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID);
107 SceneObjectPart sop1 = sog1.RootPart; 107 SceneObjectPart sop1 = sog1.RootPart;
@@ -127,7 +127,7 @@ namespace OpenSim.Region.Framework.Tests
127 TestHelper.InMethod(); 127 TestHelper.InMethod();
128// log4net.Config.XmlConfigurator.Configure(); 128// log4net.Config.XmlConfigurator.Configure();
129 129
130 Scene scene = SceneSetupHelpers.SetupScene("inventory"); 130 Scene scene = SceneSetupHelpers.SetupScene();
131 UserAccount user1 = CreateUser(scene); 131 UserAccount user1 = CreateUser(scene);
132 SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID); 132 SceneObjectGroup sog1 = CreateSO1(scene, user1.PrincipalID);
133 SceneObjectPart sop1 = sog1.RootPart; 133 SceneObjectPart sop1 = sog1.RootPart;
diff --git a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
index 6b70865..dbf9e0f 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/UuidGathererTests.cs
@@ -47,7 +47,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests
47 [SetUp] 47 [SetUp]
48 public void Init() 48 public void Init()
49 { 49 {
50 m_assetService = new MockAssetService(); 50 // FIXME: We don't need a full scene here - it would be enough to set up the asset service.
51 Scene scene = SceneSetupHelpers.SetupScene();
52 m_assetService = scene.AssetService;
51 m_uuidGatherer = new UuidGatherer(m_assetService); 53 m_uuidGatherer = new UuidGatherer(m_assetService);
52 } 54 }
53 55
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 83906d7..77b1535 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -298,10 +298,20 @@ namespace OpenSim.Region.Framework.Scenes
298 if (null != objectAsset) 298 if (null != objectAsset)
299 { 299 {
300 string xml = Utils.BytesToString(objectAsset.Data); 300 string xml = Utils.BytesToString(objectAsset.Data);
301 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); 301
302 302 CoalescedSceneObjects coa;
303 if (null != sog) 303 if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa))
304 GatherAssetUuids(sog, assetUuids); 304 {
305 foreach (SceneObjectGroup sog in coa.Objects)
306 GatherAssetUuids(sog, assetUuids);
307 }
308 else
309 {
310 SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml);
311
312 if (null != sog)
313 GatherAssetUuids(sog, assetUuids);
314 }
305 } 315 }
306 } 316 }
307 317