aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs422
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPMaterial.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPVehicle.cs742
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs315
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs697
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs37
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs303
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs1216
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs1320
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs769
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs445
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs122
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs367
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
20 files changed, 5407 insertions, 1502 deletions
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index b3debb0..2365cfe 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -55,8 +55,12 @@ namespace OpenSim.Region.Framework.Scenes
55 55
56 public delegate void OnTerrainTickDelegate(); 56 public delegate void OnTerrainTickDelegate();
57 57
58 public delegate void OnTerrainUpdateDelegate();
59
58 public event OnTerrainTickDelegate OnTerrainTick; 60 public event OnTerrainTickDelegate OnTerrainTick;
59 61
62 public event OnTerrainUpdateDelegate OnTerrainUpdate;
63
60 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 64 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
61 65
62 public event OnBackupDelegate OnBackup; 66 public event OnBackupDelegate OnBackup;
@@ -889,6 +893,26 @@ namespace OpenSim.Region.Framework.Scenes
889 } 893 }
890 } 894 }
891 } 895 }
896 public void TriggerTerrainUpdate()
897 {
898 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
899 if (handlerTerrainUpdate != null)
900 {
901 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
902 {
903 try
904 {
905 d();
906 }
907 catch (Exception e)
908 {
909 m_log.ErrorFormat(
910 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
911 e.Message, e.StackTrace);
912 }
913 }
914 }
915 }
892 916
893 public void TriggerTerrainTick() 917 public void TriggerTerrainTick()
894 { 918 {
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
new file mode 100644
index 0000000..b7b0d27
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -0,0 +1,422 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker
3//
4
5using System;
6using System.Timers;
7using System.Collections;
8using System.Collections.Generic;
9using System.IO;
10using System.Diagnostics;
11using System.Reflection;
12using System.Threading;
13using OpenMetaverse;
14using OpenSim.Framework;
15using OpenSim.Region.Framework.Interfaces;
16using OpenSim.Region.Physics.Manager;
17using OpenSim.Region.Framework.Scenes.Serialization;
18using System.Runtime.Serialization.Formatters.Binary;
19using System.Runtime.Serialization;
20using Timer = System.Timers.Timer;
21using log4net;
22
23namespace OpenSim.Region.Framework.Scenes
24{
25 [Serializable]
26 public class KeyframeMotion
27 {
28 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
29
30 public enum PlayMode : int
31 {
32 Forward = 0,
33 Reverse = 1,
34 Loop = 2,
35 PingPong = 3
36 };
37
38 [Flags]
39 public enum DataFormat : int
40 {
41 Translation = 1,
42 Rotation = 2
43 }
44
45 [Serializable]
46 public struct Keyframe
47 {
48 public Vector3? Position;
49 public Quaternion? Rotation;
50 public Quaternion StartRotation;
51 public int TimeMS;
52 public int TimeTotal;
53 public Vector3 AngularVelocity;
54 };
55
56 private Vector3 m_basePosition;
57 private Quaternion m_baseRotation;
58 private Vector3 m_serializedPosition;
59
60 private Keyframe m_currentFrame;
61 private List<Keyframe> m_frames = new List<Keyframe>();
62
63 private Keyframe[] m_keyframes;
64
65 [NonSerialized()]
66 protected Timer m_timer = new Timer();
67
68 [NonSerialized()]
69 private SceneObjectGroup m_group;
70
71 private PlayMode m_mode = PlayMode.Forward;
72 private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation;
73
74 private bool m_running = false;
75 [NonSerialized()]
76 private bool m_selected = false;
77
78 private int m_iterations = 0;
79
80 private const double timerInterval = 50.0;
81
82 public DataFormat Data
83 {
84 get { return m_data; }
85 }
86
87 public bool Selected
88 {
89 set
90 {
91 if (value)
92 {
93 // Once we're let go, recompute positions
94 if (m_selected)
95 UpdateSceneObject(m_group);
96 }
97 else
98 {
99 // Save selection position in case we get moved
100 if (!m_selected)
101 m_serializedPosition = m_group.AbsolutePosition;
102 }
103 m_selected = value; }
104 }
105
106 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
107 {
108 MemoryStream ms = new MemoryStream(data);
109
110 BinaryFormatter fmt = new BinaryFormatter();
111
112 KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms);
113
114 // This will be started when position is updated
115 newMotion.m_timer = new Timer();
116 newMotion.m_timer.Interval = (int)timerInterval;
117 newMotion.m_timer.AutoReset = true;
118 newMotion.m_timer.Elapsed += newMotion.OnTimer;
119
120 return newMotion;
121 }
122
123 public void UpdateSceneObject(SceneObjectGroup grp)
124 {
125 m_group = grp;
126 Vector3 offset = grp.AbsolutePosition - m_serializedPosition;
127
128 m_basePosition += offset;
129 m_currentFrame.Position += offset;
130 for (int i = 0 ; i < m_frames.Count ; i++)
131 {
132 Keyframe k = m_frames[i];
133 k.Position += offset;
134 m_frames[i] = k;
135 }
136
137 if (m_running)
138 Start();
139 }
140
141 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
142 {
143 m_mode = mode;
144 m_data = data;
145
146 m_group = grp;
147 m_basePosition = grp.AbsolutePosition;
148 m_baseRotation = grp.GroupRotation;
149
150 m_timer.Interval = (int)timerInterval;
151 m_timer.AutoReset = true;
152 m_timer.Elapsed += OnTimer;
153 }
154
155 public void SetKeyframes(Keyframe[] frames)
156 {
157 m_keyframes = frames;
158 }
159
160 public void Start()
161 {
162 if (m_keyframes.Length > 0)
163 m_timer.Start();
164 m_running = true;
165 }
166
167 public void Stop()
168 {
169 // Failed object creation
170 if (m_timer == null)
171 return;
172 m_timer.Stop();
173
174 m_basePosition = m_group.AbsolutePosition;
175 m_baseRotation = m_group.GroupRotation;
176
177 m_group.RootPart.Velocity = Vector3.Zero;
178 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
179 m_group.SendGroupRootTerseUpdate();
180
181 m_frames.Clear();
182 m_running = false;
183 }
184
185 public void Pause()
186 {
187 m_group.RootPart.Velocity = Vector3.Zero;
188 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
189 m_group.SendGroupRootTerseUpdate();
190
191 m_timer.Stop();
192 m_running = false;
193 }
194
195 private void GetNextList()
196 {
197 m_frames.Clear();
198 Vector3 pos = m_basePosition;
199 Quaternion rot = m_baseRotation;
200
201 if (m_mode == PlayMode.Loop || m_mode == PlayMode.PingPong || m_iterations == 0)
202 {
203 int direction = 1;
204 if (m_mode == PlayMode.Reverse || ((m_mode == PlayMode.PingPong) && ((m_iterations & 1) != 0)))
205 direction = -1;
206
207 int start = 0;
208 int end = m_keyframes.Length;
209// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
210// end = m_keyframes.Length - 1;
211
212 if (direction < 0)
213 {
214 start = m_keyframes.Length - 1;
215 end = -1;
216// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
217// end = 0;
218 }
219
220 for (int i = start; i != end ; i += direction)
221 {
222 Keyframe k = m_keyframes[i];
223
224 if (k.Position.HasValue)
225 k.Position = (k.Position * direction) + pos;
226 else
227 k.Position = pos;
228
229 k.StartRotation = rot;
230 if (k.Rotation.HasValue)
231 {
232 if (direction == -1)
233 k.Rotation = Quaternion.Conjugate((Quaternion)k.Rotation);
234 k.Rotation = rot * k.Rotation;
235 }
236 else
237 {
238 k.Rotation = rot;
239 }
240
241 float angle = 0;
242
243 float aa = k.StartRotation.X * k.StartRotation.X + k.StartRotation.Y * k.StartRotation.Y + k.StartRotation.Z * k.StartRotation.Z + k.StartRotation.W * k.StartRotation.W;
244 float bb = ((Quaternion)k.Rotation).X * ((Quaternion)k.Rotation).X + ((Quaternion)k.Rotation).Y * ((Quaternion)k.Rotation).Y + ((Quaternion)k.Rotation).Z * ((Quaternion)k.Rotation).Z + ((Quaternion)k.Rotation).W * ((Quaternion)k.Rotation).W;
245 float aa_bb = aa * bb;
246
247 if (aa_bb == 0)
248 {
249 angle = 0;
250 }
251 else
252 {
253 float ab = k.StartRotation.X * ((Quaternion)k.Rotation).X +
254 k.StartRotation.Y * ((Quaternion)k.Rotation).Y +
255 k.StartRotation.Z * ((Quaternion)k.Rotation).Z +
256 k.StartRotation.W * ((Quaternion)k.Rotation).W;
257 float q = (ab * ab) / aa_bb;
258
259 if (q > 1.0f)
260 {
261 angle = 0;
262 }
263 else
264 {
265 angle = (float)Math.Acos(2 * q - 1);
266 }
267 }
268
269 k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000));
270 k.TimeTotal = k.TimeMS;
271
272 m_frames.Add(k);
273
274 pos = (Vector3)k.Position;
275 rot = (Quaternion)k.Rotation;
276 }
277
278 m_basePosition = pos;
279 m_baseRotation = rot;
280
281 m_iterations++;
282 }
283 }
284
285 protected void OnTimer(object sender, ElapsedEventArgs e)
286 {
287 if (m_frames.Count == 0)
288 {
289 GetNextList();
290
291 if (m_frames.Count == 0)
292 {
293 Stop();
294 return;
295 }
296
297 m_currentFrame = m_frames[0];
298 }
299
300 if (m_selected)
301 {
302 if (m_group.RootPart.Velocity != Vector3.Zero)
303 {
304 m_group.RootPart.Velocity = Vector3.Zero;
305 m_group.SendGroupRootTerseUpdate();
306 }
307 return;
308 }
309
310 // Do the frame processing
311 double steps = (double)m_currentFrame.TimeMS / timerInterval;
312 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
313
314 if (steps <= 1.0)
315 {
316 m_currentFrame.TimeMS = 0;
317
318 m_group.AbsolutePosition = (Vector3)m_currentFrame.Position;
319 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
320 }
321 else
322 {
323 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
324 Vector3 motionThisFrame = v / (float)steps;
325 v = v * 1000 / m_currentFrame.TimeMS;
326
327 bool update = false;
328
329 if (Vector3.Mag(motionThisFrame) >= 0.05f)
330 {
331 m_group.AbsolutePosition += motionThisFrame;
332 m_group.RootPart.Velocity = v;
333 update = true;
334 }
335
336 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
337 {
338 Quaternion current = m_group.GroupRotation;
339
340 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
341
342 float angle = 0;
343
344 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
345 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
346 float aa_bb = aa * bb;
347
348 if (aa_bb == 0)
349 {
350 angle = 0;
351 }
352 else
353 {
354 float ab = current.X * step.X +
355 current.Y * step.Y +
356 current.Z * step.Z +
357 current.W * step.W;
358 float q = (ab * ab) / aa_bb;
359
360 if (q > 1.0f)
361 {
362 angle = 0;
363 }
364 else
365 {
366 angle = (float)Math.Acos(2 * q - 1);
367 }
368 }
369
370 if (angle > 0.01f)
371 {
372 m_group.UpdateGroupRotationR(step);
373 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
374 update = true;
375 }
376 }
377
378 if (update)
379 m_group.SendGroupRootTerseUpdate();
380 }
381
382 m_currentFrame.TimeMS -= (int)timerInterval;
383
384 if (m_currentFrame.TimeMS <= 0)
385 {
386 m_group.RootPart.Velocity = Vector3.Zero;
387 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
388 m_group.SendGroupRootTerseUpdate();
389
390 m_frames.RemoveAt(0);
391 if (m_frames.Count > 0)
392 m_currentFrame = m_frames[0];
393 }
394 }
395
396 public Byte[] Serialize()
397 {
398 MemoryStream ms = new MemoryStream();
399 m_timer.Stop();
400
401 BinaryFormatter fmt = new BinaryFormatter();
402 SceneObjectGroup tmp = m_group;
403 m_group = null;
404 m_serializedPosition = tmp.AbsolutePosition;
405 fmt.Serialize(ms, this);
406 m_group = tmp;
407 return ms.ToArray();
408 }
409
410 public void CrossingFailure()
411 {
412 // The serialization has stopped the timer, so let's wait a moment
413 // then retry the crossing. We'll get back here if it fails.
414 Util.FireAndForget(delegate (object x)
415 {
416 Thread.Sleep(60000);
417 if (m_running)
418 m_timer.Start();
419 });
420 }
421 }
422}
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 1b10e3c..0a34a4c 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -157,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
157 157
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 159 {
160 uint pqueue = ComputeDistancePriority(client,entity,true); 160 uint pqueue = ComputeDistancePriority(client,entity,false);
161 161
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 163 if (presence != null)
@@ -226,7 +226,7 @@ namespace OpenSim.Region.Framework.Scenes
226 226
227 for (int i = 0; i < queues - 1; i++) 227 for (int i = 0; i < queues - 1; i++)
228 { 228 {
229 if (distance < 10 * Math.Pow(2.0,i)) 229 if (distance < 30 * Math.Pow(2.0,i))
230 break; 230 break;
231 pqueue++; 231 pqueue++;
232 } 232 }
diff --git a/OpenSim/Region/Framework/Scenes/SOPMaterial.cs b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
new file mode 100644
index 0000000..10ac37c
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
@@ -0,0 +1,95 @@
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 OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Region.Framework.Scenes
34{
35 public static class SOPMaterialData
36 {
37 public enum SopMaterial : int // redundante and not in use for now
38 {
39 Stone = 0,
40 Metal = 1,
41 Glass = 2,
42 Wood = 3,
43 Flesh = 4,
44 Plastic = 5,
45 Rubber = 6,
46 light = 7 // compatibility with old viewers
47 }
48
49 private struct MaterialData
50 {
51 public float friction;
52 public float bounce;
53 public MaterialData(float f, float b)
54 {
55 friction = f;
56 bounce = b;
57 }
58 }
59
60 private static MaterialData[] m_materialdata = {
61 new MaterialData(0.8f,0.4f), // Stone
62 new MaterialData(0.3f,0.4f), // Metal
63 new MaterialData(0.2f,0.7f), // Glass
64 new MaterialData(0.6f,0.5f), // Wood
65 new MaterialData(0.9f,0.3f), // Flesh
66 new MaterialData(0.4f,0.7f), // Plastic
67 new MaterialData(0.9f,0.95f), // Rubber
68 new MaterialData(0.0f,0.0f) // light ??
69 };
70
71 public static Material MaxMaterial
72 {
73 get { return (Material)(m_materialdata.Length - 1); }
74 }
75
76 public static float friction(Material material)
77 {
78 int indx = (int)material;
79 if (indx < m_materialdata.Length)
80 return (m_materialdata[indx].friction);
81 else
82 return 0;
83 }
84
85 public static float bounce(Material material)
86 {
87 int indx = (int)material;
88 if (indx < m_materialdata.Length)
89 return (m_materialdata[indx].bounce);
90 else
91 return 0;
92 }
93
94 }
95} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/SOPVehicle.cs b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
new file mode 100644
index 0000000..d3c2d27
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
@@ -0,0 +1,742 @@
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 OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Physics.Manager;
33using System.Xml;
34using OpenSim.Framework.Serialization;
35using OpenSim.Framework.Serialization.External;
36using OpenSim.Region.Framework.Scenes.Serialization;
37using OpenSim.Region.Framework.Scenes.Serialization;
38
39namespace OpenSim.Region.Framework.Scenes
40{
41 public class SOPVehicle
42 {
43 public VehicleData vd;
44
45 public Vehicle Type
46 {
47 get { return vd.m_type; }
48 }
49
50 public SOPVehicle()
51 {
52 vd = new VehicleData();
53 ProcessTypeChange(Vehicle.TYPE_NONE); // is needed?
54 }
55
56 public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
57 {
58 float len;
59 float timestep = 0.01f;
60 switch (pParam)
61 {
62 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
63 if (pValue < 0f) pValue = 0f;
64 if (pValue > 1f) pValue = 1f;
65 vd.m_angularDeflectionEfficiency = pValue;
66 break;
67 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
68 if (pValue < timestep) pValue = timestep;
69 vd.m_angularDeflectionTimescale = pValue;
70 break;
71 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
72 if (pValue < timestep) pValue = timestep;
73 else if (pValue > 120) pValue = 120;
74 vd.m_angularMotorDecayTimescale = pValue;
75 break;
76 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
77 if (pValue < timestep) pValue = timestep;
78 vd.m_angularMotorTimescale = pValue;
79 break;
80 case Vehicle.BANKING_EFFICIENCY:
81 if (pValue < -1f) pValue = -1f;
82 if (pValue > 1f) pValue = 1f;
83 vd.m_bankingEfficiency = pValue;
84 break;
85 case Vehicle.BANKING_MIX:
86 if (pValue < 0f) pValue = 0f;
87 if (pValue > 1f) pValue = 1f;
88 vd.m_bankingMix = pValue;
89 break;
90 case Vehicle.BANKING_TIMESCALE:
91 if (pValue < timestep) pValue = timestep;
92 vd.m_bankingTimescale = pValue;
93 break;
94 case Vehicle.BUOYANCY:
95 if (pValue < -1f) pValue = -1f;
96 if (pValue > 1f) pValue = 1f;
97 vd.m_VehicleBuoyancy = pValue;
98 break;
99 case Vehicle.HOVER_EFFICIENCY:
100 if (pValue < 0f) pValue = 0f;
101 if (pValue > 1f) pValue = 1f;
102 vd.m_VhoverEfficiency = pValue;
103 break;
104 case Vehicle.HOVER_HEIGHT:
105 vd.m_VhoverHeight = pValue;
106 break;
107 case Vehicle.HOVER_TIMESCALE:
108 if (pValue < timestep) pValue = timestep;
109 vd.m_VhoverTimescale = pValue;
110 break;
111 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
112 if (pValue < 0f) pValue = 0f;
113 if (pValue > 1f) pValue = 1f;
114 vd.m_linearDeflectionEfficiency = pValue;
115 break;
116 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
117 if (pValue < timestep) pValue = timestep;
118 vd.m_linearDeflectionTimescale = pValue;
119 break;
120 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
121 if (pValue < timestep) pValue = timestep;
122 else if (pValue > 120) pValue = 120;
123 vd.m_linearMotorDecayTimescale = pValue;
124 break;
125 case Vehicle.LINEAR_MOTOR_TIMESCALE:
126 if (pValue < timestep) pValue = timestep;
127 vd.m_linearMotorTimescale = pValue;
128 break;
129 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
130 if (pValue < 0f) pValue = 0f;
131 if (pValue > 1f) pValue = 1f;
132 vd.m_verticalAttractionEfficiency = pValue;
133 break;
134 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
135 if (pValue < timestep) pValue = timestep;
136 vd.m_verticalAttractionTimescale = pValue;
137 break;
138
139 // These are vector properties but the engine lets you use a single float value to
140 // set all of the components to the same value
141 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
142 if (pValue < timestep) pValue = timestep;
143 vd.m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
144 break;
145 case Vehicle.ANGULAR_MOTOR_DIRECTION:
146 vd.m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
147 len = vd.m_angularMotorDirection.Length();
148 if (len > 12.566f)
149 vd.m_angularMotorDirection *= (12.566f / len);
150 break;
151 case Vehicle.LINEAR_FRICTION_TIMESCALE:
152 if (pValue < timestep) pValue = timestep;
153 vd.m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
154 break;
155 case Vehicle.LINEAR_MOTOR_DIRECTION:
156 vd.m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
157 len = vd.m_linearMotorDirection.Length();
158 if (len > 30.0f)
159 vd.m_linearMotorDirection *= (30.0f / len);
160 break;
161 case Vehicle.LINEAR_MOTOR_OFFSET:
162 vd.m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
163 len = vd.m_linearMotorOffset.Length();
164 if (len > 100.0f)
165 vd.m_linearMotorOffset *= (100.0f / len);
166 break;
167 }
168 }//end ProcessFloatVehicleParam
169
170 public void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
171 {
172 float len;
173 float timestep = 0.01f;
174 switch (pParam)
175 {
176 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
177 if (pValue.X < timestep) pValue.X = timestep;
178 if (pValue.Y < timestep) pValue.Y = timestep;
179 if (pValue.Z < timestep) pValue.Z = timestep;
180
181 vd.m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
182 break;
183 case Vehicle.ANGULAR_MOTOR_DIRECTION:
184 vd.m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
185 // Limit requested angular speed to 2 rps= 4 pi rads/sec
186 len = vd.m_angularMotorDirection.Length();
187 if (len > 12.566f)
188 vd.m_angularMotorDirection *= (12.566f / len);
189 break;
190 case Vehicle.LINEAR_FRICTION_TIMESCALE:
191 if (pValue.X < timestep) pValue.X = timestep;
192 if (pValue.Y < timestep) pValue.Y = timestep;
193 if (pValue.Z < timestep) pValue.Z = timestep;
194 vd.m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
195 break;
196 case Vehicle.LINEAR_MOTOR_DIRECTION:
197 vd.m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
198 len = vd.m_linearMotorDirection.Length();
199 if (len > 30.0f)
200 vd.m_linearMotorDirection *= (30.0f / len);
201 break;
202 case Vehicle.LINEAR_MOTOR_OFFSET:
203 vd.m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
204 len = vd.m_linearMotorOffset.Length();
205 if (len > 100.0f)
206 vd.m_linearMotorOffset *= (100.0f / len);
207 break;
208 }
209 }//end ProcessVectorVehicleParam
210
211 public void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
212 {
213 switch (pParam)
214 {
215 case Vehicle.REFERENCE_FRAME:
216 vd.m_referenceFrame = Quaternion.Inverse(pValue);
217 break;
218 }
219 }//end ProcessRotationVehicleParam
220
221 public void ProcessVehicleFlags(int pParam, bool remove)
222 {
223 if (remove)
224 {
225 vd.m_flags &= ~((VehicleFlag)pParam);
226 }
227 else
228 {
229 vd.m_flags |= (VehicleFlag)pParam;
230 }
231 }//end ProcessVehicleFlags
232
233 public void ProcessTypeChange(Vehicle pType)
234 {
235 vd.m_linearMotorDirection = Vector3.Zero;
236 vd.m_angularMotorDirection = Vector3.Zero;
237 vd.m_linearMotorOffset = Vector3.Zero;
238 vd.m_referenceFrame = Quaternion.Identity;
239
240 // Set Defaults For Type
241 vd.m_type = pType;
242 switch (pType)
243 {
244 case Vehicle.TYPE_NONE:
245 vd.m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
246 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
247 vd.m_linearMotorTimescale = 1000;
248 vd.m_linearMotorDecayTimescale = 120;
249 vd.m_angularMotorTimescale = 1000;
250 vd.m_angularMotorDecayTimescale = 1000;
251 vd.m_VhoverHeight = 0;
252 vd.m_VhoverEfficiency = 1;
253 vd.m_VhoverTimescale = 1000;
254 vd.m_VehicleBuoyancy = 0;
255 vd.m_linearDeflectionEfficiency = 0;
256 vd.m_linearDeflectionTimescale = 1000;
257 vd.m_angularDeflectionEfficiency = 0;
258 vd.m_angularDeflectionTimescale = 1000;
259 vd.m_bankingEfficiency = 0;
260 vd.m_bankingMix = 1;
261 vd.m_bankingTimescale = 1000;
262 vd.m_verticalAttractionEfficiency = 0;
263 vd.m_verticalAttractionTimescale = 1000;
264
265 vd.m_flags = (VehicleFlag)0;
266 break;
267
268 case Vehicle.TYPE_SLED:
269 vd.m_linearFrictionTimescale = new Vector3(30, 1, 1000);
270 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
271 vd.m_linearMotorTimescale = 1000;
272 vd.m_linearMotorDecayTimescale = 120;
273 vd.m_angularMotorTimescale = 1000;
274 vd.m_angularMotorDecayTimescale = 120;
275 vd.m_VhoverHeight = 0;
276 vd.m_VhoverEfficiency = 1;
277 vd.m_VhoverTimescale = 10;
278 vd.m_VehicleBuoyancy = 0;
279 vd.m_linearDeflectionEfficiency = 1;
280 vd.m_linearDeflectionTimescale = 1;
281 vd.m_angularDeflectionEfficiency = 0;
282 vd.m_angularDeflectionTimescale = 1000;
283 vd.m_bankingEfficiency = 0;
284 vd.m_bankingMix = 1;
285 vd.m_bankingTimescale = 10;
286 vd.m_flags &=
287 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
288 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
289 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
290 break;
291 case Vehicle.TYPE_CAR:
292 vd.m_linearFrictionTimescale = new Vector3(100, 2, 1000);
293 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
294 vd.m_linearMotorTimescale = 1;
295 vd.m_linearMotorDecayTimescale = 60;
296 vd.m_angularMotorTimescale = 1;
297 vd.m_angularMotorDecayTimescale = 0.8f;
298 vd.m_VhoverHeight = 0;
299 vd.m_VhoverEfficiency = 0;
300 vd.m_VhoverTimescale = 1000;
301 vd.m_VehicleBuoyancy = 0;
302 vd.m_linearDeflectionEfficiency = 1;
303 vd.m_linearDeflectionTimescale = 2;
304 vd.m_angularDeflectionEfficiency = 0;
305 vd.m_angularDeflectionTimescale = 10;
306 vd.m_verticalAttractionEfficiency = 1f;
307 vd.m_verticalAttractionTimescale = 10f;
308 vd.m_bankingEfficiency = -0.2f;
309 vd.m_bankingMix = 1;
310 vd.m_bankingTimescale = 1;
311 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
312 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
313 VehicleFlag.LIMIT_MOTOR_UP | VehicleFlag.HOVER_UP_ONLY);
314 break;
315 case Vehicle.TYPE_BOAT:
316 vd.m_linearFrictionTimescale = new Vector3(10, 3, 2);
317 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
318 vd.m_linearMotorTimescale = 5;
319 vd.m_linearMotorDecayTimescale = 60;
320 vd.m_angularMotorTimescale = 4;
321 vd.m_angularMotorDecayTimescale = 4;
322 vd.m_VhoverHeight = 0;
323 vd.m_VhoverEfficiency = 0.5f;
324 vd.m_VhoverTimescale = 2;
325 vd.m_VehicleBuoyancy = 1;
326 vd.m_linearDeflectionEfficiency = 0.5f;
327 vd.m_linearDeflectionTimescale = 3;
328 vd.m_angularDeflectionEfficiency = 0.5f;
329 vd.m_angularDeflectionTimescale = 5;
330 vd.m_verticalAttractionEfficiency = 0.5f;
331 vd.m_verticalAttractionTimescale = 5f;
332 vd.m_bankingEfficiency = -0.3f;
333 vd.m_bankingMix = 0.8f;
334 vd.m_bankingTimescale = 1;
335 vd.m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
336 VehicleFlag.HOVER_GLOBAL_HEIGHT |
337 VehicleFlag.HOVER_UP_ONLY |
338 VehicleFlag.LIMIT_ROLL_ONLY);
339 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
340 VehicleFlag.LIMIT_MOTOR_UP |
341 VehicleFlag.HOVER_WATER_ONLY);
342 break;
343 case Vehicle.TYPE_AIRPLANE:
344 vd.m_linearFrictionTimescale = new Vector3(200, 10, 5);
345 vd.m_angularFrictionTimescale = new Vector3(20, 20, 20);
346 vd.m_linearMotorTimescale = 2;
347 vd.m_linearMotorDecayTimescale = 60;
348 vd.m_angularMotorTimescale = 4;
349 vd.m_angularMotorDecayTimescale = 8;
350 vd.m_VhoverHeight = 0;
351 vd.m_VhoverEfficiency = 0.5f;
352 vd.m_VhoverTimescale = 1000;
353 vd.m_VehicleBuoyancy = 0;
354 vd.m_linearDeflectionEfficiency = 0.5f;
355 vd.m_linearDeflectionTimescale = 0.5f;
356 vd.m_angularDeflectionEfficiency = 1;
357 vd.m_angularDeflectionTimescale = 2;
358 vd.m_verticalAttractionEfficiency = 0.9f;
359 vd.m_verticalAttractionTimescale = 2f;
360 vd.m_bankingEfficiency = 1;
361 vd.m_bankingMix = 0.7f;
362 vd.m_bankingTimescale = 2;
363 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
364 VehicleFlag.HOVER_TERRAIN_ONLY |
365 VehicleFlag.HOVER_GLOBAL_HEIGHT |
366 VehicleFlag.HOVER_UP_ONLY |
367 VehicleFlag.NO_DEFLECTION_UP |
368 VehicleFlag.LIMIT_MOTOR_UP);
369 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
370 break;
371 case Vehicle.TYPE_BALLOON:
372 vd.m_linearFrictionTimescale = new Vector3(5, 5, 5);
373 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
374 vd.m_linearMotorTimescale = 5;
375 vd.m_linearMotorDecayTimescale = 60;
376 vd.m_angularMotorTimescale = 6;
377 vd.m_angularMotorDecayTimescale = 10;
378 vd.m_VhoverHeight = 5;
379 vd.m_VhoverEfficiency = 0.8f;
380 vd.m_VhoverTimescale = 10;
381 vd.m_VehicleBuoyancy = 1;
382 vd.m_linearDeflectionEfficiency = 0;
383 vd.m_linearDeflectionTimescale = 5;
384 vd.m_angularDeflectionEfficiency = 0;
385 vd.m_angularDeflectionTimescale = 5;
386 vd.m_verticalAttractionEfficiency = 0f;
387 vd.m_verticalAttractionTimescale = 1000f;
388 vd.m_bankingEfficiency = 0;
389 vd.m_bankingMix = 0.7f;
390 vd.m_bankingTimescale = 5;
391 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
392 VehicleFlag.HOVER_TERRAIN_ONLY |
393 VehicleFlag.HOVER_UP_ONLY |
394 VehicleFlag.NO_DEFLECTION_UP |
395 VehicleFlag.LIMIT_MOTOR_UP);
396 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
397 VehicleFlag.HOVER_GLOBAL_HEIGHT);
398 break;
399 }
400 }
401 public void SetVehicle(PhysicsActor ph)
402 {
403 if (ph == null)
404 return;
405 ph.SetVehicle(vd);
406 }
407
408 private XmlTextWriter writer;
409
410 private void XWint(string name, int i)
411 {
412 writer.WriteElementString(name, i.ToString());
413 }
414
415 private void XWfloat(string name, float f)
416 {
417 writer.WriteElementString(name, f.ToString(Utils.EnUsCulture));
418 }
419
420 private void XWVector(string name, Vector3 vec)
421 {
422 writer.WriteStartElement(name);
423 writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
424 writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
425 writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
426 writer.WriteEndElement();
427 }
428
429 private void XWQuat(string name, Quaternion quat)
430 {
431 writer.WriteStartElement(name);
432 writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
433 writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
434 writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
435 writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
436 writer.WriteEndElement();
437 }
438
439 public void ToXml2(XmlTextWriter twriter)
440 {
441 writer = twriter;
442 writer.WriteStartElement("Vehicle");
443
444 XWint("TYPE", (int)vd.m_type);
445 XWint("FLAGS", (int)vd.m_flags);
446
447 // Linear properties
448 XWVector("LMDIR", vd.m_linearMotorDirection);
449 XWVector("LMFTIME", vd.m_linearFrictionTimescale);
450 XWfloat("LMDTIME", vd.m_linearMotorDecayTimescale);
451 XWfloat("LMTIME", vd.m_linearMotorTimescale);
452 XWVector("LMOFF", vd.m_linearMotorOffset);
453
454 //Angular properties
455 XWVector("AMDIR", vd.m_angularMotorDirection);
456 XWfloat("AMTIME", vd.m_angularMotorTimescale);
457 XWfloat("AMDTIME", vd.m_angularMotorDecayTimescale);
458 XWVector("AMFTIME", vd.m_angularFrictionTimescale);
459
460 //Deflection properties
461 XWfloat("ADEFF", vd.m_angularDeflectionEfficiency);
462 XWfloat("ADTIME", vd.m_angularDeflectionTimescale);
463 XWfloat("LDEFF", vd.m_linearDeflectionEfficiency);
464 XWfloat("LDTIME", vd.m_linearDeflectionTimescale);
465
466 //Banking properties
467 XWfloat("BEFF", vd.m_bankingEfficiency);
468 XWfloat("BMIX", vd.m_bankingMix);
469 XWfloat("BTIME", vd.m_bankingTimescale);
470
471 //Hover and Buoyancy properties
472 XWfloat("HHEI", vd.m_VhoverHeight);
473 XWfloat("HEFF", vd.m_VhoverEfficiency);
474 XWfloat("HTIME", vd.m_VhoverTimescale);
475 XWfloat("VBUO", vd.m_VehicleBuoyancy);
476
477 //Attractor properties
478 XWfloat("VAEFF", vd.m_verticalAttractionEfficiency);
479 XWfloat("VATIME", vd.m_verticalAttractionTimescale);
480
481 XWQuat("REF_FRAME", vd.m_referenceFrame);
482
483 writer.WriteEndElement();
484 writer = null;
485 }
486
487
488
489 XmlTextReader reader;
490
491 private int XRint()
492 {
493 return reader.ReadElementContentAsInt();
494 }
495
496 private float XRfloat()
497 {
498 return reader.ReadElementContentAsFloat();
499 }
500
501 public Vector3 XRvector()
502 {
503 Vector3 vec;
504 reader.ReadStartElement();
505 vec.X = reader.ReadElementContentAsFloat();
506 vec.Y = reader.ReadElementContentAsFloat();
507 vec.Z = reader.ReadElementContentAsFloat();
508 reader.ReadEndElement();
509 return vec;
510 }
511
512 public Quaternion XRquat()
513 {
514 Quaternion q;
515 reader.ReadStartElement();
516 q.X = reader.ReadElementContentAsFloat();
517 q.Y = reader.ReadElementContentAsFloat();
518 q.Z = reader.ReadElementContentAsFloat();
519 q.W = reader.ReadElementContentAsFloat();
520 reader.ReadEndElement();
521 return q;
522 }
523
524 public static bool EReadProcessors(
525 Dictionary<string, Action> processors,
526 XmlTextReader xtr)
527 {
528 bool errors = false;
529
530 string nodeName = string.Empty;
531 while (xtr.NodeType != XmlNodeType.EndElement)
532 {
533 nodeName = xtr.Name;
534
535 // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName);
536
537 Action p = null;
538 if (processors.TryGetValue(xtr.Name, out p))
539 {
540 // m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName);
541
542 try
543 {
544 p();
545 }
546 catch (Exception e)
547 {
548 errors = true;
549 if (xtr.NodeType == XmlNodeType.EndElement)
550 xtr.Read();
551 }
552 }
553 else
554 {
555 // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName);
556 xtr.ReadOuterXml(); // ignore
557 }
558 }
559
560 return errors;
561 }
562
563
564
565 public void FromXml2(XmlTextReader _reader, out bool errors)
566 {
567 errors = false;
568 reader = _reader;
569
570 Dictionary<string, Action> m_VehicleXmlProcessors
571 = new Dictionary<string, Action>();
572
573 m_VehicleXmlProcessors.Add("TYPE", ProcessXR_type);
574 m_VehicleXmlProcessors.Add("FLAGS", ProcessXR_flags);
575
576 // Linear properties
577 m_VehicleXmlProcessors.Add("LMDIR", ProcessXR_linearMotorDirection);
578 m_VehicleXmlProcessors.Add("LMFTIME", ProcessXR_linearFrictionTimescale);
579 m_VehicleXmlProcessors.Add("LMDTIME", ProcessXR_linearMotorDecayTimescale);
580 m_VehicleXmlProcessors.Add("LMTIME", ProcessXR_linearMotorTimescale);
581 m_VehicleXmlProcessors.Add("LMOFF", ProcessXR_linearMotorOffset);
582
583 //Angular properties
584 m_VehicleXmlProcessors.Add("AMDIR", ProcessXR_angularMotorDirection);
585 m_VehicleXmlProcessors.Add("AMTIME", ProcessXR_angularMotorTimescale);
586 m_VehicleXmlProcessors.Add("AMDTIME", ProcessXR_angularMotorDecayTimescale);
587 m_VehicleXmlProcessors.Add("AMFTIME", ProcessXR_angularFrictionTimescale);
588
589 //Deflection properties
590 m_VehicleXmlProcessors.Add("ADEFF", ProcessXR_angularDeflectionEfficiency);
591 m_VehicleXmlProcessors.Add("ADTIME", ProcessXR_angularDeflectionTimescale);
592 m_VehicleXmlProcessors.Add("LDEFF", ProcessXR_linearDeflectionEfficiency);
593 m_VehicleXmlProcessors.Add("LDTIME", ProcessXR_linearDeflectionTimescale);
594
595 //Banking properties
596 m_VehicleXmlProcessors.Add("BEFF", ProcessXR_bankingEfficiency);
597 m_VehicleXmlProcessors.Add("BMIX", ProcessXR_bankingMix);
598 m_VehicleXmlProcessors.Add("BTIME", ProcessXR_bankingTimescale);
599
600 //Hover and Buoyancy properties
601 m_VehicleXmlProcessors.Add("HHEI", ProcessXR_VhoverHeight);
602 m_VehicleXmlProcessors.Add("HEFF", ProcessXR_VhoverEfficiency);
603 m_VehicleXmlProcessors.Add("HTIME", ProcessXR_VhoverTimescale);
604
605 m_VehicleXmlProcessors.Add("VBUO", ProcessXR_VehicleBuoyancy);
606
607 //Attractor properties
608 m_VehicleXmlProcessors.Add("VAEFF", ProcessXR_verticalAttractionEfficiency);
609 m_VehicleXmlProcessors.Add("VATIME", ProcessXR_verticalAttractionTimescale);
610
611 m_VehicleXmlProcessors.Add("REF_FRAME", ProcessXR_referenceFrame);
612
613 vd = new VehicleData();
614
615 reader.ReadStartElement("Vehicle", String.Empty);
616
617 errors = EReadProcessors(
618 m_VehicleXmlProcessors,
619 reader);
620
621 reader.ReadEndElement();
622 reader = null;
623 }
624
625 private void ProcessXR_type()
626 {
627 vd.m_type = (Vehicle)XRint();
628 }
629 private void ProcessXR_flags()
630 {
631 vd.m_flags = (VehicleFlag)XRint();
632 }
633 // Linear properties
634 private void ProcessXR_linearMotorDirection()
635 {
636 vd.m_linearMotorDirection = XRvector();
637 }
638
639 private void ProcessXR_linearFrictionTimescale()
640 {
641 vd.m_linearFrictionTimescale = XRvector();
642 }
643
644 private void ProcessXR_linearMotorDecayTimescale()
645 {
646 vd.m_linearMotorDecayTimescale = XRfloat();
647 }
648 private void ProcessXR_linearMotorTimescale()
649 {
650 vd.m_linearMotorTimescale = XRfloat();
651 }
652 private void ProcessXR_linearMotorOffset()
653 {
654 vd.m_linearMotorOffset = XRvector();
655 }
656
657
658 //Angular properties
659 private void ProcessXR_angularMotorDirection()
660 {
661 vd.m_angularMotorDirection = XRvector();
662 }
663 private void ProcessXR_angularMotorTimescale()
664 {
665 vd.m_angularMotorTimescale = XRfloat();
666 }
667 private void ProcessXR_angularMotorDecayTimescale()
668 {
669 vd.m_angularMotorDecayTimescale = XRfloat();
670 }
671 private void ProcessXR_angularFrictionTimescale()
672 {
673 vd.m_angularFrictionTimescale = XRvector();
674 }
675
676 //Deflection properties
677 private void ProcessXR_angularDeflectionEfficiency()
678 {
679 vd.m_angularDeflectionEfficiency = XRfloat();
680 }
681 private void ProcessXR_angularDeflectionTimescale()
682 {
683 vd.m_angularDeflectionTimescale = XRfloat();
684 }
685 private void ProcessXR_linearDeflectionEfficiency()
686 {
687 vd.m_linearDeflectionEfficiency = XRfloat();
688 }
689 private void ProcessXR_linearDeflectionTimescale()
690 {
691 vd.m_linearDeflectionTimescale = XRfloat();
692 }
693
694 //Banking properties
695 private void ProcessXR_bankingEfficiency()
696 {
697 vd.m_bankingEfficiency = XRfloat();
698 }
699 private void ProcessXR_bankingMix()
700 {
701 vd.m_bankingMix = XRfloat();
702 }
703 private void ProcessXR_bankingTimescale()
704 {
705 vd.m_bankingTimescale = XRfloat();
706 }
707
708 //Hover and Buoyancy properties
709 private void ProcessXR_VhoverHeight()
710 {
711 vd.m_VhoverHeight = XRfloat();
712 }
713 private void ProcessXR_VhoverEfficiency()
714 {
715 vd.m_VhoverEfficiency = XRfloat();
716 }
717 private void ProcessXR_VhoverTimescale()
718 {
719 vd.m_VhoverTimescale = XRfloat();
720 }
721
722 private void ProcessXR_VehicleBuoyancy()
723 {
724 vd.m_VehicleBuoyancy = XRfloat();
725 }
726
727 //Attractor properties
728 private void ProcessXR_verticalAttractionEfficiency()
729 {
730 vd.m_verticalAttractionEfficiency = XRfloat();
731 }
732 private void ProcessXR_verticalAttractionTimescale()
733 {
734 vd.m_verticalAttractionTimescale = XRfloat();
735 }
736
737 private void ProcessXR_referenceFrame()
738 {
739 vd.m_referenceFrame = XRquat();
740 }
741 }
742} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 10b25ed..0089c7d 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -156,7 +156,7 @@ namespace OpenSim.Region.Framework.Scenes
156 return false; 156 return false;
157 } 157 }
158 } 158 }
159 159
160 if (InventoryService.AddItem(item)) 160 if (InventoryService.AddItem(item))
161 { 161 {
162 int userlevel = 0; 162 int userlevel = 0;
@@ -307,8 +307,7 @@ namespace OpenSim.Region.Framework.Scenes
307 307
308 // Update item with new asset 308 // Update item with new asset
309 item.AssetID = asset.FullID; 309 item.AssetID = asset.FullID;
310 if (group.UpdateInventoryItem(item)) 310 group.UpdateInventoryItem(item);
311 remoteClient.SendAgentAlertMessage("Script saved", false);
312 311
313 part.SendPropertiesToClient(remoteClient); 312 part.SendPropertiesToClient(remoteClient);
314 313
@@ -319,12 +318,7 @@ namespace OpenSim.Region.Framework.Scenes
319 { 318 {
320 // Needs to determine which engine was running it and use that 319 // Needs to determine which engine was running it and use that
321 // 320 //
322 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 321 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
323 errors = part.Inventory.GetScriptErrors(item.ItemID);
324 }
325 else
326 {
327 remoteClient.SendAgentAlertMessage("Script saved", false);
328 } 322 }
329 323
330 // Tell anyone managing scripts that a script has been reloaded/changed 324 // Tell anyone managing scripts that a script has been reloaded/changed
@@ -392,6 +386,7 @@ namespace OpenSim.Region.Framework.Scenes
392 386
393 if (UUID.Zero == transactionID) 387 if (UUID.Zero == transactionID)
394 { 388 {
389 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
395 item.Name = itemUpd.Name; 390 item.Name = itemUpd.Name;
396 item.Description = itemUpd.Description; 391 item.Description = itemUpd.Description;
397 392
@@ -779,6 +774,8 @@ namespace OpenSim.Region.Framework.Scenes
779 return; 774 return;
780 } 775 }
781 776
777 if (newName == null) newName = item.Name;
778
782 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 779 AssetBase asset = AssetService.Get(item.AssetID.ToString());
783 780
784 if (asset != null) 781 if (asset != null)
@@ -835,6 +832,24 @@ namespace OpenSim.Region.Framework.Scenes
835 } 832 }
836 833
837 /// <summary> 834 /// <summary>
835 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
836 /// </summary>
837 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
838 {
839 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
840 foreach (InventoryItemBase b in items)
841 {
842 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
843 InventoryItemBase n = InventoryService.GetItem(b);
844 n.Folder = destfolder;
845 moveitems.Add(n);
846 remoteClient.SendInventoryItemCreateUpdate(n, 0);
847 }
848
849 MoveInventoryItem(remoteClient, moveitems);
850 }
851
852 /// <summary>
838 /// Move an item within the agent's inventory. 853 /// Move an item within the agent's inventory.
839 /// </summary> 854 /// </summary>
840 /// <param name="remoteClient"></param> 855 /// <param name="remoteClient"></param>
@@ -1177,6 +1192,10 @@ namespace OpenSim.Region.Framework.Scenes
1177 { 1192 {
1178 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1193 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1179 1194
1195 // Can't move a null item
1196 if (itemId == UUID.Zero)
1197 return;
1198
1180 if (null == part) 1199 if (null == part)
1181 { 1200 {
1182 m_log.WarnFormat( 1201 m_log.WarnFormat(
@@ -1281,21 +1300,28 @@ namespace OpenSim.Region.Framework.Scenes
1281 return; 1300 return;
1282 } 1301 }
1283 1302
1284 if (part.OwnerID != destPart.OwnerID) 1303 // Can't transfer this
1304 //
1305 if (part.OwnerID != destPart.OwnerID && (srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1306 return;
1307
1308 bool overrideNoMod = false;
1309 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1310 overrideNoMod = true;
1311
1312 if (part.OwnerID != destPart.OwnerID && (destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1285 { 1313 {
1286 // Source must have transfer permissions 1314 // object cannot copy items to an object owned by a different owner
1287 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) 1315 // unless llAllowInventoryDrop has been called
1288 return;
1289 1316
1290 // Object cannot copy items to an object owned by a different owner 1317 return;
1291 // unless llAllowInventoryDrop has been called on the destination
1292 if ((destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1293 return;
1294 } 1318 }
1295 1319
1296 // must have both move and modify permission to put an item in an object 1320 // must have both move and modify permission to put an item in an object
1297 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1321 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1322 {
1298 return; 1323 return;
1324 }
1299 1325
1300 TaskInventoryItem destTaskItem = new TaskInventoryItem(); 1326 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1301 1327
@@ -1351,6 +1377,14 @@ namespace OpenSim.Region.Framework.Scenes
1351 1377
1352 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1378 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1353 { 1379 {
1380 SceneObjectPart destPart = GetSceneObjectPart(destID);
1381 if (destPart != null) // Move into a prim
1382 {
1383 foreach(UUID itemID in items)
1384 MoveTaskInventoryItem(destID, host, itemID);
1385 return destID; // Prim folder ID == prim ID
1386 }
1387
1354 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1388 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1355 1389
1356 UUID newFolderID = UUID.Random(); 1390 UUID newFolderID = UUID.Random();
@@ -1536,12 +1570,12 @@ namespace OpenSim.Region.Framework.Scenes
1536 agentTransactions.HandleTaskItemUpdateFromTransaction( 1570 agentTransactions.HandleTaskItemUpdateFromTransaction(
1537 remoteClient, part, transactionID, currentItem); 1571 remoteClient, part, transactionID, currentItem);
1538 1572
1539 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1573// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1540 remoteClient.SendAgentAlertMessage("Notecard saved", false); 1574// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1541 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1575// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1542 remoteClient.SendAgentAlertMessage("Script saved", false); 1576// remoteClient.SendAgentAlertMessage("Script saved", false);
1543 else 1577// else
1544 remoteClient.SendAgentAlertMessage("Item saved", false); 1578// remoteClient.SendAgentAlertMessage("Item saved", false);
1545 } 1579 }
1546 } 1580 }
1547 1581
@@ -1725,7 +1759,7 @@ namespace OpenSim.Region.Framework.Scenes
1725 } 1759 }
1726 1760
1727 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1761 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1728 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1762 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1729 agentID); 1763 agentID);
1730 AssetService.Store(asset); 1764 AssetService.Store(asset);
1731 1765
@@ -1881,23 +1915,32 @@ namespace OpenSim.Region.Framework.Scenes
1881 // build a list of eligible objects 1915 // build a list of eligible objects
1882 List<uint> deleteIDs = new List<uint>(); 1916 List<uint> deleteIDs = new List<uint>();
1883 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1917 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1884 1918 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1885 // Start with true for both, then remove the flags if objects
1886 // that we can't derez are part of the selection
1887 bool permissionToTake = true;
1888 bool permissionToTakeCopy = true;
1889 bool permissionToDelete = true;
1890 1919
1891 foreach (uint localID in localIDs) 1920 foreach (uint localID in localIDs)
1892 { 1921 {
1922 // Start with true for both, then remove the flags if objects
1923 // that we can't derez are part of the selection
1924 bool permissionToTake = true;
1925 bool permissionToTakeCopy = true;
1926 bool permissionToDelete = true;
1927
1893 // Invalid id 1928 // Invalid id
1894 SceneObjectPart part = GetSceneObjectPart(localID); 1929 SceneObjectPart part = GetSceneObjectPart(localID);
1895 if (part == null) 1930 if (part == null)
1931 {
1932 //Client still thinks the object exists, kill it
1933 deleteIDs.Add(localID);
1896 continue; 1934 continue;
1935 }
1897 1936
1898 // Already deleted by someone else 1937 // Already deleted by someone else
1899 if (part.ParentGroup.IsDeleted) 1938 if (part.ParentGroup.IsDeleted)
1939 {
1940 //Client still thinks the object exists, kill it
1941 deleteIDs.Add(localID);
1900 continue; 1942 continue;
1943 }
1901 1944
1902 // Can't delete child prims 1945 // Can't delete child prims
1903 if (part != part.ParentGroup.RootPart) 1946 if (part != part.ParentGroup.RootPart)
@@ -1905,9 +1948,6 @@ namespace OpenSim.Region.Framework.Scenes
1905 1948
1906 SceneObjectGroup grp = part.ParentGroup; 1949 SceneObjectGroup grp = part.ParentGroup;
1907 1950
1908 deleteIDs.Add(localID);
1909 deleteGroups.Add(grp);
1910
1911 if (remoteClient == null) 1951 if (remoteClient == null)
1912 { 1952 {
1913 // Autoreturn has a null client. Nothing else does. So 1953 // Autoreturn has a null client. Nothing else does. So
@@ -1924,81 +1964,193 @@ namespace OpenSim.Region.Framework.Scenes
1924 } 1964 }
1925 else 1965 else
1926 { 1966 {
1927 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1967 if (action == DeRezAction.TakeCopy)
1968 {
1969 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1970 permissionToTakeCopy = false;
1971 }
1972 else
1973 {
1928 permissionToTakeCopy = false; 1974 permissionToTakeCopy = false;
1929 1975 }
1930 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1976 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1931 permissionToTake = false; 1977 permissionToTake = false;
1932 1978
1933 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1979 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1934 permissionToDelete = false; 1980 permissionToDelete = false;
1935 } 1981 }
1936 }
1937 1982
1938 // Handle god perms 1983 // Handle god perms
1939 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1984 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1940 { 1985 {
1941 permissionToTake = true; 1986 permissionToTake = true;
1942 permissionToTakeCopy = true; 1987 permissionToTakeCopy = true;
1943 permissionToDelete = true; 1988 permissionToDelete = true;
1944 } 1989 }
1945 1990
1946 // If we're re-saving, we don't even want to delete 1991 // If we're re-saving, we don't even want to delete
1947 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1992 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1948 permissionToDelete = false; 1993 permissionToDelete = false;
1949 1994
1950 // if we want to take a copy, we also don't want to delete 1995 // if we want to take a copy, we also don't want to delete
1951 // Note: after this point, the permissionToTakeCopy flag 1996 // Note: after this point, the permissionToTakeCopy flag
1952 // becomes irrelevant. It already includes the permissionToTake 1997 // becomes irrelevant. It already includes the permissionToTake
1953 // permission and after excluding no copy items here, we can 1998 // permission and after excluding no copy items here, we can
1954 // just use that. 1999 // just use that.
1955 if (action == DeRezAction.TakeCopy) 2000 if (action == DeRezAction.TakeCopy)
1956 { 2001 {
1957 // If we don't have permission, stop right here 2002 // If we don't have permission, stop right here
1958 if (!permissionToTakeCopy) 2003 if (!permissionToTakeCopy)
1959 return; 2004 return;
1960 2005
1961 permissionToTake = true; 2006 permissionToTake = true;
1962 // Don't delete 2007 // Don't delete
1963 permissionToDelete = false; 2008 permissionToDelete = false;
1964 } 2009 }
1965 2010
1966 if (action == DeRezAction.Return) 2011 if (action == DeRezAction.Return)
1967 {
1968 if (remoteClient != null)
1969 { 2012 {
1970 if (Permissions.CanReturnObjects( 2013 if (remoteClient != null)
1971 null,
1972 remoteClient.AgentId,
1973 deleteGroups))
1974 { 2014 {
1975 permissionToTake = true; 2015 if (Permissions.CanReturnObjects(
1976 permissionToDelete = true; 2016 null,
1977 2017 remoteClient.AgentId,
1978 foreach (SceneObjectGroup g in deleteGroups) 2018 deleteGroups))
1979 { 2019 {
1980 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 2020 permissionToTake = true;
2021 permissionToDelete = true;
2022
2023 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1981 } 2024 }
1982 } 2025 }
2026 else // Auto return passes through here with null agent
2027 {
2028 permissionToTake = true;
2029 permissionToDelete = true;
2030 }
1983 } 2031 }
1984 else // Auto return passes through here with null agent 2032
2033 if (permissionToTake && (!permissionToDelete))
2034 takeGroups.Add(grp);
2035
2036 if (permissionToDelete)
1985 { 2037 {
1986 permissionToTake = true; 2038 if (permissionToTake)
1987 permissionToDelete = true; 2039 deleteGroups.Add(grp);
2040 deleteIDs.Add(grp.LocalId);
1988 } 2041 }
1989 } 2042 }
1990 2043
1991 if (permissionToTake) 2044 SendKillObject(deleteIDs);
2045
2046 if (deleteGroups.Count > 0)
1992 { 2047 {
2048 foreach (SceneObjectGroup g in deleteGroups)
2049 deleteIDs.Remove(g.LocalId);
2050
1993 m_asyncSceneObjectDeleter.DeleteToInventory( 2051 m_asyncSceneObjectDeleter.DeleteToInventory(
1994 action, destinationID, deleteGroups, remoteClient, 2052 action, destinationID, deleteGroups, remoteClient,
1995 permissionToDelete); 2053 true);
2054 }
2055 if (takeGroups.Count > 0)
2056 {
2057 m_asyncSceneObjectDeleter.DeleteToInventory(
2058 action, destinationID, takeGroups, remoteClient,
2059 false);
1996 } 2060 }
1997 else if (permissionToDelete) 2061 if (deleteIDs.Count > 0)
1998 { 2062 {
1999 foreach (SceneObjectGroup g in deleteGroups) 2063 foreach (SceneObjectGroup g in deleteGroups)
2000 DeleteSceneObject(g, false); 2064 DeleteSceneObject(g, true);
2065 }
2066 }
2067
2068 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2069 {
2070 itemID = UUID.Zero;
2071 if (grp != null)
2072 {
2073 Vector3 inventoryStoredPosition = new Vector3
2074 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
2075 ? 250
2076 : grp.AbsolutePosition.X)
2077 ,
2078 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
2079 ? 250
2080 : grp.AbsolutePosition.X,
2081 grp.AbsolutePosition.Z);
2082
2083 Vector3 originalPosition = grp.AbsolutePosition;
2084
2085 grp.AbsolutePosition = inventoryStoredPosition;
2086
2087 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2088
2089 grp.AbsolutePosition = originalPosition;
2090
2091 AssetBase asset = CreateAsset(
2092 grp.GetPartName(grp.LocalId),
2093 grp.GetPartDescription(grp.LocalId),
2094 (sbyte)AssetType.Object,
2095 Utils.StringToBytes(sceneObjectXml),
2096 remoteClient.AgentId);
2097 AssetService.Store(asset);
2098
2099 InventoryItemBase item = new InventoryItemBase();
2100 item.CreatorId = grp.RootPart.CreatorID.ToString();
2101 item.CreatorData = grp.RootPart.CreatorData;
2102 item.Owner = remoteClient.AgentId;
2103 item.ID = UUID.Random();
2104 item.AssetID = asset.FullID;
2105 item.Description = asset.Description;
2106 item.Name = asset.Name;
2107 item.AssetType = asset.Type;
2108 item.InvType = (int)InventoryType.Object;
2109
2110 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
2111 if (folder != null)
2112 item.Folder = folder.ID;
2113 else // oopsies
2114 item.Folder = UUID.Zero;
2115
2116 // Set up base perms properly
2117 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2118 permsBase &= grp.RootPart.BaseMask;
2119 permsBase |= (uint)PermissionMask.Move;
2120
2121 // Make sure we don't lock it
2122 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2123
2124 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2125 {
2126 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2127 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2128 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2129 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2130 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2131 }
2132 else
2133 {
2134 item.BasePermissions = permsBase;
2135 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2136 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2137 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2138 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2139 }
2140 item.CreationDate = Util.UnixTimeSinceEpoch();
2141
2142 // sets itemID so client can show item as 'attached' in inventory
2143 grp.FromItemID = item.ID;
2144
2145 if (AddInventoryItem(item))
2146 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2147 else
2148 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2149
2150 itemID = item.ID;
2151 return item.AssetID;
2001 } 2152 }
2153 return UUID.Zero;
2002 } 2154 }
2003 2155
2004 /// <summary> 2156 /// <summary>
@@ -2127,6 +2279,9 @@ namespace OpenSim.Region.Framework.Scenes
2127 2279
2128 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2280 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2129 { 2281 {
2282 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2283 return;
2284
2130 SceneObjectPart part = GetSceneObjectPart(objectID); 2285 SceneObjectPart part = GetSceneObjectPart(objectID);
2131 if (part == null) 2286 if (part == null)
2132 return; 2287 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 87ffc74..35ac908 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -138,12 +138,12 @@ namespace OpenSim.Region.Framework.Scenes
138 { 138 {
139 SceneObjectGroup sog = part.ParentGroup; 139 SceneObjectGroup sog = part.ParentGroup;
140 sog.SendPropertiesToClient(remoteClient); 140 sog.SendPropertiesToClient(remoteClient);
141 sog.IsSelected = true;
142 141
143 // A prim is only tainted if it's allowed to be edited by the person clicking it. 142 // A prim is only tainted if it's allowed to be edited by the person clicking it.
144 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) 143 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
145 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) 144 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
146 { 145 {
146 sog.IsSelected = true;
147 EventManager.TriggerParcelPrimCountTainted(); 147 EventManager.TriggerParcelPrimCountTainted();
148 } 148 }
149 } 149 }
@@ -215,7 +215,9 @@ namespace OpenSim.Region.Framework.Scenes
215 // handled by group, but by prim. Legacy cruft. 215 // handled by group, but by prim. Legacy cruft.
216 // TODO: Make selection flagging per prim! 216 // TODO: Make selection flagging per prim!
217 // 217 //
218 part.ParentGroup.IsSelected = false; 218 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
219 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
220 part.ParentGroup.IsSelected = false;
219 221
220 if (part.ParentGroup.IsAttachment) 222 if (part.ParentGroup.IsAttachment)
221 isAttachment = true; 223 isAttachment = true;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index e488fe1..3e08128 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -118,6 +118,7 @@ namespace OpenSim.Region.Framework.Scenes
118 // TODO: need to figure out how allow client agents but deny 118 // TODO: need to figure out how allow client agents but deny
119 // root agents when ACL denies access to root agent 119 // root agents when ACL denies access to root agent
120 public bool m_strictAccessControl = true; 120 public bool m_strictAccessControl = true;
121 public bool m_seeIntoBannedRegion = false;
121 public int MaxUndoCount = 5; 122 public int MaxUndoCount = 5;
122 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 123 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
123 public bool LoginLock = false; 124 public bool LoginLock = false;
@@ -133,12 +134,14 @@ namespace OpenSim.Region.Framework.Scenes
133 134
134 protected int m_splitRegionID; 135 protected int m_splitRegionID;
135 protected Timer m_restartWaitTimer = new Timer(); 136 protected Timer m_restartWaitTimer = new Timer();
137 protected Timer m_timerWatchdog = new Timer();
136 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 138 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
137 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 139 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
138 protected string m_simulatorVersion = "OpenSimulator Server"; 140 protected string m_simulatorVersion = "OpenSimulator Server";
139 protected ModuleLoader m_moduleLoader; 141 protected ModuleLoader m_moduleLoader;
140 protected AgentCircuitManager m_authenticateHandler; 142 protected AgentCircuitManager m_authenticateHandler;
141 protected SceneCommunicationService m_sceneGridService; 143 protected SceneCommunicationService m_sceneGridService;
144 protected ISnmpModule m_snmpService = null;
142 145
143 protected ISimulationDataService m_SimulationDataService; 146 protected ISimulationDataService m_SimulationDataService;
144 protected IEstateDataService m_EstateDataService; 147 protected IEstateDataService m_EstateDataService;
@@ -201,7 +204,7 @@ namespace OpenSim.Region.Framework.Scenes
201 private int m_update_events = 1; 204 private int m_update_events = 1;
202 private int m_update_backup = 200; 205 private int m_update_backup = 200;
203 private int m_update_terrain = 50; 206 private int m_update_terrain = 50;
204// private int m_update_land = 1; 207 private int m_update_land = 10;
205 private int m_update_coarse_locations = 50; 208 private int m_update_coarse_locations = 50;
206 209
207 private int agentMS; 210 private int agentMS;
@@ -220,6 +223,7 @@ namespace OpenSim.Region.Framework.Scenes
220 /// </summary> 223 /// </summary>
221 private int m_lastFrameTick; 224 private int m_lastFrameTick;
222 225
226 public bool CombineRegions = false;
223 /// <summary> 227 /// <summary>
224 /// Tick at which the last maintenance run occurred. 228 /// Tick at which the last maintenance run occurred.
225 /// </summary> 229 /// </summary>
@@ -250,6 +254,11 @@ namespace OpenSim.Region.Framework.Scenes
250 /// </summary> 254 /// </summary>
251 private int m_LastLogin; 255 private int m_LastLogin;
252 256
257 private int m_lastIncoming;
258 private int m_lastOutgoing;
259 private int m_hbRestarts = 0;
260
261
253 /// <summary> 262 /// <summary>
254 /// Thread that runs the scene loop. 263 /// Thread that runs the scene loop.
255 /// </summary> 264 /// </summary>
@@ -265,7 +274,7 @@ namespace OpenSim.Region.Framework.Scenes
265 private volatile bool m_shuttingDown; 274 private volatile bool m_shuttingDown;
266 275
267// private int m_lastUpdate; 276// private int m_lastUpdate;
268// private bool m_firstHeartbeat = true; 277 private bool m_firstHeartbeat = true;
269 278
270 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; 279 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
271 private bool m_reprioritizationEnabled = true; 280 private bool m_reprioritizationEnabled = true;
@@ -310,6 +319,19 @@ namespace OpenSim.Region.Framework.Scenes
310 get { return m_sceneGridService; } 319 get { return m_sceneGridService; }
311 } 320 }
312 321
322 public ISnmpModule SnmpService
323 {
324 get
325 {
326 if (m_snmpService == null)
327 {
328 m_snmpService = RequestModuleInterface<ISnmpModule>();
329 }
330
331 return m_snmpService;
332 }
333 }
334
313 public ISimulationDataService SimulationDataService 335 public ISimulationDataService SimulationDataService
314 { 336 {
315 get 337 get
@@ -592,6 +614,8 @@ namespace OpenSim.Region.Framework.Scenes
592 m_EstateDataService = estateDataService; 614 m_EstateDataService = estateDataService;
593 m_regionHandle = m_regInfo.RegionHandle; 615 m_regionHandle = m_regInfo.RegionHandle;
594 m_regionName = m_regInfo.RegionName; 616 m_regionName = m_regInfo.RegionName;
617 m_lastIncoming = 0;
618 m_lastOutgoing = 0;
595 619
596 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 620 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
597 m_asyncSceneObjectDeleter.Enabled = true; 621 m_asyncSceneObjectDeleter.Enabled = true;
@@ -672,98 +696,107 @@ namespace OpenSim.Region.Framework.Scenes
672 696
673 // Region config overrides global config 697 // Region config overrides global config
674 // 698 //
675 if (m_config.Configs["Startup"] != null) 699 try
676 { 700 {
677 IConfig startupConfig = m_config.Configs["Startup"]; 701 if (m_config.Configs["Startup"] != null)
678
679 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
680 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
681 if (!m_useBackup)
682 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
683
684 //Animation states
685 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
686
687 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
688 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
689
690 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
691 if (RegionInfo.NonphysPrimMax > 0)
692 { 702 {
693 m_maxNonphys = RegionInfo.NonphysPrimMax; 703 IConfig startupConfig = m_config.Configs["Startup"];
694 }
695 704
696 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 705 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
706 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
707 if (!m_useBackup)
708 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
709
710 //Animation states
711 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
697 712
698 if (RegionInfo.PhysPrimMax > 0) 713 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
699 { 714 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
700 m_maxPhys = RegionInfo.PhysPrimMax;
701 }
702 715
703 // Here, if clamping is requested in either global or 716 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
704 // local config, it will be used 717 if (RegionInfo.NonphysPrimMax > 0)
705 // 718 {
706 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize); 719 m_maxNonphys = RegionInfo.NonphysPrimMax;
707 if (RegionInfo.ClampPrimSize) 720 }
708 {
709 m_clampPrimSize = true;
710 }
711 721
712 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 722 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
713 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
714 m_dontPersistBefore =
715 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
716 m_dontPersistBefore *= 10000000;
717 m_persistAfter =
718 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
719 m_persistAfter *= 10000000;
720 723
721 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 724 if (RegionInfo.PhysPrimMax > 0)
725 {
726 m_maxPhys = RegionInfo.PhysPrimMax;
727 }
722 728
723 IConfig packetConfig = m_config.Configs["PacketPool"]; 729 // Here, if clamping is requested in either global or
724 if (packetConfig != null) 730 // local config, it will be used
725 { 731 //
726 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); 732 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
727 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); 733 if (RegionInfo.ClampPrimSize)
728 } 734 {
735 m_clampPrimSize = true;
736 }
729 737
730 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 738 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
739 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
740 m_dontPersistBefore =
741 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
742 m_dontPersistBefore *= 10000000;
743 m_persistAfter =
744 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
745 m_persistAfter *= 10000000;
731 746
732 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 747 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
733 if (m_generateMaptiles) 748 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
734 { 749
735 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0); 750 IConfig packetConfig = m_config.Configs["PacketPool"];
736 if (maptileRefresh != 0) 751 if (packetConfig != null)
737 { 752 {
738 m_mapGenerationTimer.Interval = maptileRefresh * 1000; 753 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
739 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister; 754 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
740 m_mapGenerationTimer.AutoReset = true;
741 m_mapGenerationTimer.Start();
742 } 755 }
743 }
744 else
745 {
746 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
747 UUID tileID;
748 756
749 if (UUID.TryParse(tile, out tileID)) 757 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
758 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
759 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
760
761 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
762 if (m_generateMaptiles)
750 { 763 {
751 RegionInfo.RegionSettings.TerrainImageID = tileID; 764 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
765 if (maptileRefresh != 0)
766 {
767 m_mapGenerationTimer.Interval = maptileRefresh * 1000;
768 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister;
769 m_mapGenerationTimer.AutoReset = true;
770 m_mapGenerationTimer.Start();
771 }
752 } 772 }
753 } 773 else
774 {
775 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
776 UUID tileID;
754 777
755 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime); 778 if (UUID.TryParse(tile, out tileID))
756 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup); 779 {
757 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 780 RegionInfo.RegionSettings.TerrainImageID = tileID;
758 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement); 781 }
759 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events); 782 }
760 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
761 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
762 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
763 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
764 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
765 783
766 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates); 784 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
785 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup);
786 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
787 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement);
788 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events);
789 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
790 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
791 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
792 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
793 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
794 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates);
795 }
796 }
797 catch (Exception e)
798 {
799 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
767 } 800 }
768 801
769 #endregion Region Config 802 #endregion Region Config
@@ -1194,7 +1227,22 @@ namespace OpenSim.Region.Framework.Scenes
1194 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1227 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1195 if (m_heartbeatThread != null) 1228 if (m_heartbeatThread != null)
1196 { 1229 {
1230 m_hbRestarts++;
1231 if(m_hbRestarts > 10)
1232 Environment.Exit(1);
1233 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1234
1235//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1236//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1237//proc.EnableRaisingEvents=false;
1238//proc.StartInfo.FileName = "/bin/kill";
1239//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1240//proc.Start();
1241//proc.WaitForExit();
1242//Thread.Sleep(1000);
1243//Environment.Exit(1);
1197 m_heartbeatThread.Abort(); 1244 m_heartbeatThread.Abort();
1245 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1198 m_heartbeatThread = null; 1246 m_heartbeatThread = null;
1199 } 1247 }
1200// m_lastUpdate = Util.EnvironmentTickCount(); 1248// m_lastUpdate = Util.EnvironmentTickCount();
@@ -1507,6 +1555,8 @@ namespace OpenSim.Region.Framework.Scenes
1507 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); 1555 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc);
1508 maintc = (int)(MinFrameTime * 1000) - maintc; 1556 maintc = (int)(MinFrameTime * 1000) - maintc;
1509 1557
1558 m_firstHeartbeat = false;
1559
1510 if (maintc > 0) 1560 if (maintc > 0)
1511 Thread.Sleep(maintc); 1561 Thread.Sleep(maintc);
1512 1562
@@ -1536,9 +1586,9 @@ namespace OpenSim.Region.Framework.Scenes
1536 1586
1537 private void CheckAtTargets() 1587 private void CheckAtTargets()
1538 { 1588 {
1539 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1589 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1540 lock (m_groupsWithTargets) 1590 lock (m_groupsWithTargets)
1541 objs = m_groupsWithTargets.Values; 1591 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1542 1592
1543 foreach (SceneObjectGroup entry in objs) 1593 foreach (SceneObjectGroup entry in objs)
1544 entry.checkAtTargets(); 1594 entry.checkAtTargets();
@@ -1619,7 +1669,7 @@ namespace OpenSim.Region.Framework.Scenes
1619 msg.fromAgentName = "Server"; 1669 msg.fromAgentName = "Server";
1620 msg.dialog = (byte)19; // Object msg 1670 msg.dialog = (byte)19; // Object msg
1621 msg.fromGroup = false; 1671 msg.fromGroup = false;
1622 msg.offline = (byte)0; 1672 msg.offline = (byte)1;
1623 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1673 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1624 msg.Position = Vector3.Zero; 1674 msg.Position = Vector3.Zero;
1625 msg.RegionID = RegionInfo.RegionID.Guid; 1675 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1841,6 +1891,19 @@ namespace OpenSim.Region.Framework.Scenes
1841 EventManager.TriggerPrimsLoaded(this); 1891 EventManager.TriggerPrimsLoaded(this);
1842 } 1892 }
1843 1893
1894 public bool SuportsRayCastFiltered()
1895 {
1896 if (PhysicsScene == null)
1897 return false;
1898 return PhysicsScene.SuportsRaycastWorldFiltered();
1899 }
1900
1901 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
1902 {
1903 if (PhysicsScene == null)
1904 return null;
1905 return PhysicsScene.RaycastWorld(position, direction, length, Count,filter);
1906 }
1844 1907
1845 /// <summary> 1908 /// <summary>
1846 /// Gets a new rez location based on the raycast and the size of the object that is being rezzed. 1909 /// Gets a new rez location based on the raycast and the size of the object that is being rezzed.
@@ -1857,14 +1920,24 @@ namespace OpenSim.Region.Framework.Scenes
1857 /// <returns></returns> 1920 /// <returns></returns>
1858 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1921 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1859 { 1922 {
1923
1924 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1925 Vector3 wpos = Vector3.Zero;
1926 // Check for water surface intersection from above
1927 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1928 {
1929 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1930 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1931 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1932 wpos.Z = wheight;
1933 }
1934
1860 Vector3 pos = Vector3.Zero; 1935 Vector3 pos = Vector3.Zero;
1861 if (RayEndIsIntersection == (byte)1) 1936 if (RayEndIsIntersection == (byte)1)
1862 { 1937 {
1863 pos = RayEnd; 1938 pos = RayEnd;
1864 return pos;
1865 } 1939 }
1866 1940 else if (RayTargetID != UUID.Zero)
1867 if (RayTargetID != UUID.Zero)
1868 { 1941 {
1869 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1942 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1870 1943
@@ -1886,7 +1959,7 @@ namespace OpenSim.Region.Framework.Scenes
1886 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1959 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1887 1960
1888 // Un-comment out the following line to Get Raytrace results printed to the console. 1961 // Un-comment out the following line to Get Raytrace results printed to the console.
1889 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1962 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1890 float ScaleOffset = 0.5f; 1963 float ScaleOffset = 0.5f;
1891 1964
1892 // If we hit something 1965 // If we hit something
@@ -1909,13 +1982,10 @@ namespace OpenSim.Region.Framework.Scenes
1909 //pos.Z -= 0.25F; 1982 //pos.Z -= 0.25F;
1910 1983
1911 } 1984 }
1912
1913 return pos;
1914 } 1985 }
1915 else 1986 else
1916 { 1987 {
1917 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1988 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1918
1919 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1989 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1920 1990
1921 // Un-comment the following line to print the raytrace results to the console. 1991 // Un-comment the following line to print the raytrace results to the console.
@@ -1924,13 +1994,12 @@ namespace OpenSim.Region.Framework.Scenes
1924 if (ei.HitTF) 1994 if (ei.HitTF)
1925 { 1995 {
1926 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1996 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1927 } else 1997 }
1998 else
1928 { 1999 {
1929 // fall back to our stupid functionality 2000 // fall back to our stupid functionality
1930 pos = RayEnd; 2001 pos = RayEnd;
1931 } 2002 }
1932
1933 return pos;
1934 } 2003 }
1935 } 2004 }
1936 else 2005 else
@@ -1941,8 +2010,12 @@ namespace OpenSim.Region.Framework.Scenes
1941 //increase height so its above the ground. 2010 //increase height so its above the ground.
1942 //should be getting the normal of the ground at the rez point and using that? 2011 //should be getting the normal of the ground at the rez point and using that?
1943 pos.Z += scale.Z / 2f; 2012 pos.Z += scale.Z / 2f;
1944 return pos; 2013// return pos;
1945 } 2014 }
2015
2016 // check against posible water intercept
2017 if (wpos.Z > pos.Z) pos = wpos;
2018 return pos;
1946 } 2019 }
1947 2020
1948 2021
@@ -2032,7 +2105,10 @@ namespace OpenSim.Region.Framework.Scenes
2032 public bool AddRestoredSceneObject( 2105 public bool AddRestoredSceneObject(
2033 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2106 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2034 { 2107 {
2035 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2108 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
2109 if (result)
2110 sceneObject.IsDeleted = false;
2111 return result;
2036 } 2112 }
2037 2113
2038 /// <summary> 2114 /// <summary>
@@ -2124,6 +2200,15 @@ namespace OpenSim.Region.Framework.Scenes
2124 /// </summary> 2200 /// </summary>
2125 public void DeleteAllSceneObjects() 2201 public void DeleteAllSceneObjects()
2126 { 2202 {
2203 DeleteAllSceneObjects(false);
2204 }
2205
2206 /// <summary>
2207 /// Delete every object from the scene. This does not include attachments worn by avatars.
2208 /// </summary>
2209 public void DeleteAllSceneObjects(bool exceptNoCopy)
2210 {
2211 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2127 lock (Entities) 2212 lock (Entities)
2128 { 2213 {
2129 EntityBase[] entities = Entities.GetEntities(); 2214 EntityBase[] entities = Entities.GetEntities();
@@ -2132,11 +2217,24 @@ namespace OpenSim.Region.Framework.Scenes
2132 if (e is SceneObjectGroup) 2217 if (e is SceneObjectGroup)
2133 { 2218 {
2134 SceneObjectGroup sog = (SceneObjectGroup)e; 2219 SceneObjectGroup sog = (SceneObjectGroup)e;
2135 if (!sog.IsAttachment) 2220 if (sog != null && !sog.IsAttachment)
2136 DeleteSceneObject((SceneObjectGroup)e, false); 2221 {
2222 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2223 {
2224 DeleteSceneObject((SceneObjectGroup)e, false);
2225 }
2226 else
2227 {
2228 toReturn.Add((SceneObjectGroup)e);
2229 }
2230 }
2137 } 2231 }
2138 } 2232 }
2139 } 2233 }
2234 if (toReturn.Count > 0)
2235 {
2236 returnObjects(toReturn.ToArray(), UUID.Zero);
2237 }
2140 } 2238 }
2141 2239
2142 /// <summary> 2240 /// <summary>
@@ -2171,6 +2269,8 @@ namespace OpenSim.Region.Framework.Scenes
2171 } 2269 }
2172 2270
2173 group.DeleteGroupFromScene(silent); 2271 group.DeleteGroupFromScene(silent);
2272 if (!silent)
2273 SendKillObject(new List<uint>() { group.LocalId });
2174 2274
2175// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2275// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2176 } 2276 }
@@ -2460,6 +2560,8 @@ namespace OpenSim.Region.Framework.Scenes
2460 2560
2461 if (newPosition != Vector3.Zero) 2561 if (newPosition != Vector3.Zero)
2462 newObject.RootPart.GroupPosition = newPosition; 2562 newObject.RootPart.GroupPosition = newPosition;
2563 if (newObject.RootPart.KeyframeMotion != null)
2564 newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2463 2565
2464 if (!AddSceneObject(newObject)) 2566 if (!AddSceneObject(newObject))
2465 { 2567 {
@@ -2528,10 +2630,17 @@ namespace OpenSim.Region.Framework.Scenes
2528 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2630 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2529 public bool AddSceneObject(SceneObjectGroup sceneObject) 2631 public bool AddSceneObject(SceneObjectGroup sceneObject)
2530 { 2632 {
2633 if (sceneObject.OwnerID == UUID.Zero)
2634 {
2635 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2636 return false;
2637 }
2638
2531 // If the user is banned, we won't let any of their objects 2639 // If the user is banned, we won't let any of their objects
2532 // enter. Period. 2640 // enter. Period.
2533 // 2641 //
2534 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2642 int flags = GetUserFlags(sceneObject.OwnerID);
2643 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2535 { 2644 {
2536 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2645 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2537 2646
@@ -2577,12 +2686,23 @@ namespace OpenSim.Region.Framework.Scenes
2577 } 2686 }
2578 else 2687 else
2579 { 2688 {
2689 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2580 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2690 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2581 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2691 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2582 } 2692 }
2693 if (sceneObject.OwnerID == UUID.Zero)
2694 {
2695 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2696 return false;
2697 }
2583 } 2698 }
2584 else 2699 else
2585 { 2700 {
2701 if (sceneObject.OwnerID == UUID.Zero)
2702 {
2703 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2704 return false;
2705 }
2586 AddRestoredSceneObject(sceneObject, true, false); 2706 AddRestoredSceneObject(sceneObject, true, false);
2587 2707
2588 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2708 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2611,6 +2731,24 @@ namespace OpenSim.Region.Framework.Scenes
2611 return 2; // StateSource.PrimCrossing 2731 return 2; // StateSource.PrimCrossing
2612 } 2732 }
2613 2733
2734 public int GetUserFlags(UUID user)
2735 {
2736 //Unfortunately the SP approach means that the value is cached until region is restarted
2737 /*
2738 ScenePresence sp;
2739 if (TryGetScenePresence(user, out sp))
2740 {
2741 return sp.UserFlags;
2742 }
2743 else
2744 {
2745 */
2746 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2747 if (uac == null)
2748 return 0;
2749 return uac.UserFlags;
2750 //}
2751 }
2614 #endregion 2752 #endregion
2615 2753
2616 #region Add/Remove Avatar Methods 2754 #region Add/Remove Avatar Methods
@@ -2624,7 +2762,7 @@ namespace OpenSim.Region.Framework.Scenes
2624 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 2762 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2625 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2763 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2626 2764
2627// CheckHeartbeat(); 2765 CheckHeartbeat();
2628 2766
2629 ScenePresence sp = GetScenePresence(client.AgentId); 2767 ScenePresence sp = GetScenePresence(client.AgentId);
2630 2768
@@ -2677,7 +2815,13 @@ namespace OpenSim.Region.Framework.Scenes
2677 2815
2678 EventManager.TriggerOnNewClient(client); 2816 EventManager.TriggerOnNewClient(client);
2679 if (vialogin) 2817 if (vialogin)
2818 {
2680 EventManager.TriggerOnClientLogin(client); 2819 EventManager.TriggerOnClientLogin(client);
2820 // Send initial parcel data
2821 Vector3 pos = sp.AbsolutePosition;
2822 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2823 land.SendLandUpdateToClient(client);
2824 }
2681 2825
2682 return sp; 2826 return sp;
2683 } 2827 }
@@ -2767,19 +2911,12 @@ namespace OpenSim.Region.Framework.Scenes
2767 // and the scene presence and the client, if they exist 2911 // and the scene presence and the client, if they exist
2768 try 2912 try
2769 { 2913 {
2770 // We need to wait for the client to make UDP contact first. 2914 ScenePresence sp = GetScenePresence(agentID);
2771 // It's the UDP contact that creates the scene presence 2915 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2772 ScenePresence sp = WaitGetScenePresence(agentID); 2916
2773 if (sp != null) 2917 if (sp != null)
2774 {
2775 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2776
2777 sp.ControllingClient.Close(); 2918 sp.ControllingClient.Close();
2778 } 2919
2779 else
2780 {
2781 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2782 }
2783 // BANG! SLASH! 2920 // BANG! SLASH!
2784 m_authenticateHandler.RemoveCircuit(agentID); 2921 m_authenticateHandler.RemoveCircuit(agentID);
2785 2922
@@ -2824,6 +2961,8 @@ namespace OpenSim.Region.Framework.Scenes
2824 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 2961 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
2825 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 2962 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
2826 2963
2964 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
2965
2827 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 2966 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
2828 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 2967 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
2829 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 2968 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -2880,6 +3019,7 @@ namespace OpenSim.Region.Framework.Scenes
2880 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3019 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2881 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3020 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2882 client.OnCopyInventoryItem += CopyInventoryItem; 3021 client.OnCopyInventoryItem += CopyInventoryItem;
3022 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2883 client.OnMoveInventoryItem += MoveInventoryItem; 3023 client.OnMoveInventoryItem += MoveInventoryItem;
2884 client.OnRemoveInventoryItem += RemoveInventoryItem; 3024 client.OnRemoveInventoryItem += RemoveInventoryItem;
2885 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3025 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2951,6 +3091,8 @@ namespace OpenSim.Region.Framework.Scenes
2951 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3091 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
2952 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3092 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
2953 3093
3094 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3095
2954 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3096 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2955 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3097 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2956 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3098 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3053,15 +3195,16 @@ namespace OpenSim.Region.Framework.Scenes
3053 /// </summary> 3195 /// </summary>
3054 /// <param name="agentId">The avatar's Unique ID</param> 3196 /// <param name="agentId">The avatar's Unique ID</param>
3055 /// <param name="client">The IClientAPI for the client</param> 3197 /// <param name="client">The IClientAPI for the client</param>
3056 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3198 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
3057 { 3199 {
3058 if (m_teleportModule != null) 3200 if (m_teleportModule != null)
3059 m_teleportModule.TeleportHome(agentId, client); 3201 return m_teleportModule.TeleportHome(agentId, client);
3060 else 3202 else
3061 { 3203 {
3062 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3204 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
3063 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3205 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
3064 } 3206 }
3207 return false;
3065 } 3208 }
3066 3209
3067 /// <summary> 3210 /// <summary>
@@ -3171,6 +3314,16 @@ namespace OpenSim.Region.Framework.Scenes
3171 /// <param name="flags"></param> 3314 /// <param name="flags"></param>
3172 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3315 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3173 { 3316 {
3317 //Add half the avatar's height so that the user doesn't fall through prims
3318 ScenePresence presence;
3319 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3320 {
3321 if (presence.Appearance != null)
3322 {
3323 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3324 }
3325 }
3326
3174 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3327 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3175 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3328 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3176 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3329 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3239,8 +3392,9 @@ namespace OpenSim.Region.Framework.Scenes
3239 regions.Remove(RegionInfo.RegionHandle); 3392 regions.Remove(RegionInfo.RegionHandle);
3240 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3393 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3241 } 3394 }
3242 3395 m_log.Debug("[Scene] Beginning ClientClosed");
3243 m_eventManager.TriggerClientClosed(agentID, this); 3396 m_eventManager.TriggerClientClosed(agentID, this);
3397 m_log.Debug("[Scene] Finished ClientClosed");
3244 } 3398 }
3245 catch (NullReferenceException) 3399 catch (NullReferenceException)
3246 { 3400 {
@@ -3302,9 +3456,10 @@ namespace OpenSim.Region.Framework.Scenes
3302 { 3456 {
3303 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3457 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3304 } 3458 }
3305 3459 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3306 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3460 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3307// CleanDroppedAttachments(); 3461// CleanDroppedAttachments();
3462 m_log.Debug("[Scene] The avatar has left the building");
3308 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3463 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3309 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3464 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3310 } 3465 }
@@ -3426,13 +3581,16 @@ namespace OpenSim.Region.Framework.Scenes
3426 sp = null; 3581 sp = null;
3427 } 3582 }
3428 3583
3429 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3430 3584
3431 //On login test land permisions 3585 //On login test land permisions
3432 if (vialogin) 3586 if (vialogin)
3433 { 3587 {
3434 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3588 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3589 if (cache != null)
3590 cache.Remove(agent.firstname + " " + agent.lastname);
3591 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3435 { 3592 {
3593 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3436 return false; 3594 return false;
3437 } 3595 }
3438 } 3596 }
@@ -3456,8 +3614,13 @@ namespace OpenSim.Region.Framework.Scenes
3456 3614
3457 try 3615 try
3458 { 3616 {
3459 if (!AuthorizeUser(agent, out reason)) 3617 // Always check estate if this is a login. Always
3460 return false; 3618 // check if banned regions are to be blacked out.
3619 if (vialogin || (!m_seeIntoBannedRegion))
3620 {
3621 if (!AuthorizeUser(agent, out reason))
3622 return false;
3623 }
3461 } 3624 }
3462 catch (Exception e) 3625 catch (Exception e)
3463 { 3626 {
@@ -3583,6 +3746,8 @@ namespace OpenSim.Region.Framework.Scenes
3583 } 3746 }
3584 3747
3585 // Honor parcel landing type and position. 3748 // Honor parcel landing type and position.
3749 /*
3750 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3586 if (land != null) 3751 if (land != null)
3587 { 3752 {
3588 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3753 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3590,26 +3755,34 @@ namespace OpenSim.Region.Framework.Scenes
3590 agent.startpos = land.LandData.UserLocation; 3755 agent.startpos = land.LandData.UserLocation;
3591 } 3756 }
3592 } 3757 }
3758 */// This is now handled properly in ScenePresence.MakeRootAgent
3593 } 3759 }
3594 3760
3595 return true; 3761 return true;
3596 } 3762 }
3597 3763
3598 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3764 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3599 { 3765 {
3600 3766 reason = String.Empty;
3601 bool banned = land.IsBannedFromLand(agent.AgentID); 3767 if (Permissions.IsGod(agentID))
3602 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3768 return true;
3769
3770 ILandObject land = LandChannel.GetLandObject(posX, posY);
3771 if (land == null)
3772 return false;
3773
3774 bool banned = land.IsBannedFromLand(agentID);
3775 bool restricted = land.IsRestrictedFromLand(agentID);
3603 3776
3604 if (banned || restricted) 3777 if (banned || restricted)
3605 { 3778 {
3606 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3779 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3607 if (nearestParcel != null) 3780 if (nearestParcel != null)
3608 { 3781 {
3609 //Move agent to nearest allowed 3782 //Move agent to nearest allowed
3610 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3783 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3611 agent.startpos.X = newPosition.X; 3784 posX = newPosition.X;
3612 agent.startpos.Y = newPosition.Y; 3785 posY = newPosition.Y;
3613 } 3786 }
3614 else 3787 else
3615 { 3788 {
@@ -3671,7 +3844,7 @@ namespace OpenSim.Region.Framework.Scenes
3671 3844
3672 if (!m_strictAccessControl) return true; 3845 if (!m_strictAccessControl) return true;
3673 if (Permissions.IsGod(agent.AgentID)) return true; 3846 if (Permissions.IsGod(agent.AgentID)) return true;
3674 3847
3675 if (AuthorizationService != null) 3848 if (AuthorizationService != null)
3676 { 3849 {
3677 if (!AuthorizationService.IsAuthorizedForRegion( 3850 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3686,7 +3859,7 @@ namespace OpenSim.Region.Framework.Scenes
3686 3859
3687 if (m_regInfo.EstateSettings != null) 3860 if (m_regInfo.EstateSettings != null)
3688 { 3861 {
3689 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3862 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3690 { 3863 {
3691 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3864 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3692 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3865 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3878,6 +4051,13 @@ namespace OpenSim.Region.Framework.Scenes
3878 4051
3879 // We have to wait until the viewer contacts this region after receiving EAC. 4052 // We have to wait until the viewer contacts this region after receiving EAC.
3880 // That calls AddNewClient, which finally creates the ScenePresence 4053 // That calls AddNewClient, which finally creates the ScenePresence
4054 int flags = GetUserFlags(cAgentData.AgentID);
4055 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4056 {
4057 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4058 return false;
4059 }
4060
3881 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4061 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3882 if (nearestParcel == null) 4062 if (nearestParcel == null)
3883 { 4063 {
@@ -3959,12 +4139,22 @@ namespace OpenSim.Region.Framework.Scenes
3959 return false; 4139 return false;
3960 } 4140 }
3961 4141
4142 public bool IncomingCloseAgent(UUID agentID)
4143 {
4144 return IncomingCloseAgent(agentID, false);
4145 }
4146
4147 public bool IncomingCloseChildAgent(UUID agentID)
4148 {
4149 return IncomingCloseAgent(agentID, true);
4150 }
4151
3962 /// <summary> 4152 /// <summary>
3963 /// Tell a single agent to disconnect from the region. 4153 /// Tell a single agent to disconnect from the region.
3964 /// </summary> 4154 /// </summary>
3965 /// <param name="regionHandle"></param>
3966 /// <param name="agentID"></param> 4155 /// <param name="agentID"></param>
3967 public bool IncomingCloseAgent(UUID agentID) 4156 /// <param name="childOnly"></param>
4157 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3968 { 4158 {
3969 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4159 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3970 4160
@@ -3976,7 +4166,7 @@ namespace OpenSim.Region.Framework.Scenes
3976 { 4166 {
3977 m_sceneGraph.removeUserCount(false); 4167 m_sceneGraph.removeUserCount(false);
3978 } 4168 }
3979 else 4169 else if (!childOnly)
3980 { 4170 {
3981 m_sceneGraph.removeUserCount(true); 4171 m_sceneGraph.removeUserCount(true);
3982 } 4172 }
@@ -3992,9 +4182,12 @@ namespace OpenSim.Region.Framework.Scenes
3992 } 4182 }
3993 else 4183 else
3994 presence.ControllingClient.SendShutdownConnectionNotice(); 4184 presence.ControllingClient.SendShutdownConnectionNotice();
4185 presence.ControllingClient.Close(false);
4186 }
4187 else if (!childOnly)
4188 {
4189 presence.ControllingClient.Close(true);
3995 } 4190 }
3996
3997 presence.ControllingClient.Close();
3998 return true; 4191 return true;
3999 } 4192 }
4000 4193
@@ -4576,35 +4769,81 @@ namespace OpenSim.Region.Framework.Scenes
4576 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4769 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4577 } 4770 }
4578 4771
4579 public int GetHealth() 4772 public int GetHealth(out int flags, out string message)
4580 { 4773 {
4581 // Returns: 4774 // Returns:
4582 // 1 = sim is up and accepting http requests. The heartbeat has 4775 // 1 = sim is up and accepting http requests. The heartbeat has
4583 // stopped and the sim is probably locked up, but a remote 4776 // stopped and the sim is probably locked up, but a remote
4584 // admin restart may succeed 4777 // admin restart may succeed
4585 // 4778 //
4586 // 2 = Sim is up and the heartbeat is running. The sim is likely 4779 // 2 = Sim is up and the heartbeat is running. The sim is likely
4587 // usable for people within and logins _may_ work 4780 // usable for people within
4781 //
4782 // 3 = Sim is up and one packet thread is running. Sim is
4783 // unstable and will not accept new logins
4784 //
4785 // 4 = Sim is up and both packet threads are running. Sim is
4786 // likely usable
4588 // 4787 //
4589 // 3 = We have seen a new user enter within the past 4 minutes 4788 // 5 = We have seen a new user enter within the past 4 minutes
4590 // which can be seen as positive confirmation of sim health 4789 // which can be seen as positive confirmation of sim health
4591 // 4790 //
4791
4792 flags = 0;
4793 message = String.Empty;
4794
4795 CheckHeartbeat();
4796
4797 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4798 {
4799 // We're still starting
4800 // 0 means "in startup", it can't happen another way, since
4801 // to get here, we must be able to accept http connections
4802 return 0;
4803 }
4804
4592 int health=1; // Start at 1, means we're up 4805 int health=1; // Start at 1, means we're up
4593 4806
4594 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 4807 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000)
4595 health += 1; 4808 {
4809 health+=1;
4810 flags |= 1;
4811 }
4812
4813 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4814 {
4815 health+=1;
4816 flags |= 2;
4817 }
4818
4819 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4820 {
4821 health+=1;
4822 flags |= 4;
4823 }
4596 else 4824 else
4825 {
4826int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4827System.Diagnostics.Process proc = new System.Diagnostics.Process();
4828proc.EnableRaisingEvents=false;
4829proc.StartInfo.FileName = "/bin/kill";
4830proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4831proc.Start();
4832proc.WaitForExit();
4833Thread.Sleep(1000);
4834Environment.Exit(1);
4835 }
4836
4837 if (flags != 7)
4597 return health; 4838 return health;
4598 4839
4599 // A login in the last 4 mins? We can't be doing too badly 4840 // A login in the last 4 mins? We can't be doing too badly
4600 // 4841 //
4601 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4842 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4602 health++; 4843 health++;
4603 else 4844 else
4604 return health; 4845 return health;
4605 4846
4606// CheckHeartbeat();
4607
4608 return health; 4847 return health;
4609 } 4848 }
4610 4849
@@ -4692,7 +4931,7 @@ namespace OpenSim.Region.Framework.Scenes
4692 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 4931 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
4693 if (wasUsingPhysics) 4932 if (wasUsingPhysics)
4694 { 4933 {
4695 jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock 4934 jointProxyObject.UpdatePrimFlags(false, false, true, false,false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
4696 } 4935 }
4697 } 4936 }
4698 4937
@@ -4791,14 +5030,14 @@ namespace OpenSim.Region.Framework.Scenes
4791 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5030 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
4792 } 5031 }
4793 5032
4794// private void CheckHeartbeat() 5033 private void CheckHeartbeat()
4795// { 5034 {
4796// if (m_firstHeartbeat) 5035 if (m_firstHeartbeat)
4797// return; 5036 return;
4798// 5037
4799// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5038 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
4800// StartTimer(); 5039 Start();
4801// } 5040 }
4802 5041
4803 public override ISceneObject DeserializeObject(string representation) 5042 public override ISceneObject DeserializeObject(string representation)
4804 { 5043 {
@@ -4810,9 +5049,14 @@ namespace OpenSim.Region.Framework.Scenes
4810 get { return m_allowScriptCrossings; } 5049 get { return m_allowScriptCrossings; }
4811 } 5050 }
4812 5051
4813 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 5052 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
4814 { 5053 {
4815 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 5054 return GetNearestAllowedPosition(avatar, null);
5055 }
5056
5057 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
5058 {
5059 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4816 5060
4817 if (nearestParcel != null) 5061 if (nearestParcel != null)
4818 { 5062 {
@@ -4821,10 +5065,7 @@ namespace OpenSim.Region.Framework.Scenes
4821 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5065 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4822 if (nearestPoint != null) 5066 if (nearestPoint != null)
4823 { 5067 {
4824// m_log.DebugFormat( 5068 Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
4825// "[SCENE]: Found a sane previous position based on velocity for {0}, sending them to {1} in {2}",
4826// avatar.Name, nearestPoint, nearestParcel.LandData.Name);
4827
4828 return nearestPoint.Value; 5069 return nearestPoint.Value;
4829 } 5070 }
4830 5071
@@ -4834,17 +5075,20 @@ namespace OpenSim.Region.Framework.Scenes
4834 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5075 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4835 if (nearestPoint != null) 5076 if (nearestPoint != null)
4836 { 5077 {
4837// m_log.DebugFormat( 5078 Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString());
4838// "[SCENE]: {0} had a zero velocity, sending them to {1}", avatar.Name, nearestPoint);
4839
4840 return nearestPoint.Value; 5079 return nearestPoint.Value;
4841 } 5080 }
4842 5081
4843 //Ultimate backup if we have no idea where they are 5082 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
4844// m_log.DebugFormat( 5083 if (dest != excludeParcel)
4845// "[SCENE]: No idea where {0} is, sending them to {1}", avatar.Name, avatar.lastKnownAllowedPosition); 5084 {
5085 // Ultimate backup if we have no idea where they are and
5086 // the last allowed position was in another parcel
5087 Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
5088 return avatar.lastKnownAllowedPosition;
5089 }
4846 5090
4847 return avatar.lastKnownAllowedPosition; 5091 // else fall through to region edge
4848 } 5092 }
4849 5093
4850 //Go to the edge, this happens in teleporting to a region with no available parcels 5094 //Go to the edge, this happens in teleporting to a region with no available parcels
@@ -4878,13 +5122,18 @@ namespace OpenSim.Region.Framework.Scenes
4878 5122
4879 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 5123 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4880 { 5124 {
5125 return GetNearestAllowedParcel(avatarId, x, y, null);
5126 }
5127
5128 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
5129 {
4881 List<ILandObject> all = AllParcels(); 5130 List<ILandObject> all = AllParcels();
4882 float minParcelDistance = float.MaxValue; 5131 float minParcelDistance = float.MaxValue;
4883 ILandObject nearestParcel = null; 5132 ILandObject nearestParcel = null;
4884 5133
4885 foreach (var parcel in all) 5134 foreach (var parcel in all)
4886 { 5135 {
4887 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 5136 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4888 { 5137 {
4889 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 5138 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4890 if (parcelDistance < minParcelDistance) 5139 if (parcelDistance < minParcelDistance)
@@ -5126,7 +5375,55 @@ namespace OpenSim.Region.Framework.Scenes
5126 mapModule.GenerateMaptile(); 5375 mapModule.GenerateMaptile();
5127 } 5376 }
5128 5377
5129 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5378// public void CleanDroppedAttachments()
5379// {
5380// List<SceneObjectGroup> objectsToDelete =
5381// new List<SceneObjectGroup>();
5382//
5383// lock (m_cleaningAttachments)
5384// {
5385// ForEachSOG(delegate (SceneObjectGroup grp)
5386// {
5387// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5388// {
5389// UUID agentID = grp.OwnerID;
5390// if (agentID == UUID.Zero)
5391// {
5392// objectsToDelete.Add(grp);
5393// return;
5394// }
5395//
5396// ScenePresence sp = GetScenePresence(agentID);
5397// if (sp == null)
5398// {
5399// objectsToDelete.Add(grp);
5400// return;
5401// }
5402// }
5403// });
5404// }
5405//
5406// foreach (SceneObjectGroup grp in objectsToDelete)
5407// {
5408// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5409// DeleteSceneObject(grp, true);
5410// }
5411// }
5412
5413 public void ThreadAlive(int threadCode)
5414 {
5415 switch(threadCode)
5416 {
5417 case 1: // Incoming
5418 m_lastIncoming = Util.EnvironmentTickCount();
5419 break;
5420 case 2: // Incoming
5421 m_lastOutgoing = Util.EnvironmentTickCount();
5422 break;
5423 }
5424 }
5425
5426 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5130 { 5427 {
5131 RegenerateMaptile(); 5428 RegenerateMaptile();
5132 5429
@@ -5145,6 +5442,14 @@ namespace OpenSim.Region.Framework.Scenes
5145 // child agent creation, thereby emulating the SL behavior. 5442 // child agent creation, thereby emulating the SL behavior.
5146 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5443 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5147 { 5444 {
5445 reason = "You are banned from the region";
5446
5447 if (Permissions.IsGod(agentID))
5448 {
5449 reason = String.Empty;
5450 return true;
5451 }
5452
5148 int num = m_sceneGraph.GetNumberOfScenePresences(); 5453 int num = m_sceneGraph.GetNumberOfScenePresences();
5149 5454
5150 if (num >= RegionInfo.RegionSettings.AgentLimit) 5455 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5156,6 +5461,41 @@ namespace OpenSim.Region.Framework.Scenes
5156 } 5461 }
5157 } 5462 }
5158 5463
5464 ScenePresence presence = GetScenePresence(agentID);
5465 IClientAPI client = null;
5466 AgentCircuitData aCircuit = null;
5467
5468 if (presence != null)
5469 {
5470 client = presence.ControllingClient;
5471 if (client != null)
5472 aCircuit = client.RequestClientInfo();
5473 }
5474
5475 // We may be called before there is a presence or a client.
5476 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5477 if (client == null)
5478 {
5479 aCircuit = new AgentCircuitData();
5480 aCircuit.AgentID = agentID;
5481 aCircuit.firstname = String.Empty;
5482 aCircuit.lastname = String.Empty;
5483 }
5484
5485 try
5486 {
5487 if (!AuthorizeUser(aCircuit, out reason))
5488 {
5489 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5490 return false;
5491 }
5492 }
5493 catch (Exception e)
5494 {
5495 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5496 return false;
5497 }
5498
5159 if (position == Vector3.Zero) // Teleport 5499 if (position == Vector3.Zero) // Teleport
5160 { 5500 {
5161 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5501 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5184,13 +5524,46 @@ namespace OpenSim.Region.Framework.Scenes
5184 } 5524 }
5185 } 5525 }
5186 } 5526 }
5527
5528 float posX = 128.0f;
5529 float posY = 128.0f;
5530
5531 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5532 {
5533 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5534 return false;
5535 }
5536 }
5537 else // Walking
5538 {
5539 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5540 if (land == null)
5541 return false;
5542
5543 bool banned = land.IsBannedFromLand(agentID);
5544 bool restricted = land.IsRestrictedFromLand(agentID);
5545
5546 if (banned || restricted)
5547 return false;
5187 } 5548 }
5188 5549
5189 reason = String.Empty; 5550 reason = String.Empty;
5190 return true; 5551 return true;
5191 } 5552 }
5192 5553
5193 /// <summary> 5554 public void StartTimerWatchdog()
5555 {
5556 m_timerWatchdog.Interval = 1000;
5557 m_timerWatchdog.Elapsed += TimerWatchdog;
5558 m_timerWatchdog.AutoReset = true;
5559 m_timerWatchdog.Start();
5560 }
5561
5562 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5563 {
5564 CheckHeartbeat();
5565 }
5566
5194 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5567 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5195 /// autopilot that moves an avatar to a sit target!. 5568 /// autopilot that moves an avatar to a sit target!.
5196 /// </summary> 5569 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 9c6b884..9b8a3ae 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index b8616e8..77e808e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Region.Framework.Scenes
88 88
89 if (neighbour != null) 89 if (neighbour != null)
90 { 90 {
91 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 91 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
92 m_scene.EventManager.TriggerOnRegionUp(neighbour); 92 m_scene.EventManager.TriggerOnRegionUp(neighbour);
93 } 93 }
94 else 94 else
@@ -102,7 +102,7 @@ namespace OpenSim.Region.Framework.Scenes
102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
103 103
104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
105 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 105 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
106 foreach (GridRegion n in neighbours) 106 foreach (GridRegion n in neighbours)
107 { 107 {
108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -182,10 +182,13 @@ namespace OpenSim.Region.Framework.Scenes
182 } 182 }
183 } 183 }
184 184
185 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
186
185 /// <summary> 187 /// <summary>
186 /// Closes a child agent on a given region 188 /// This Closes child agents on neighboring regions
189 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
187 /// </summary> 190 /// </summary>
188 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 191 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
189 { 192 {
190 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 193 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
191 194
@@ -194,31 +197,29 @@ namespace OpenSim.Region.Framework.Scenes
194 Utils.LongToUInts(regionHandle, out x, out y); 197 Utils.LongToUInts(regionHandle, out x, out y);
195 198
196 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 199 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
200 m_scene.SimulationService.CloseChildAgent(destination, agentID);
201 }
197 202
198 m_log.DebugFormat( 203 private void SendCloseChildAgentCompleted(IAsyncResult iar)
199 "[INTERGRID]: Sending close agent {0} to region at {1}-{2}", 204 {
200 agentID, destination.RegionCoordX, destination.RegionCoordY); 205 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
201 206 icon.EndInvoke(iar);
202 m_scene.SimulationService.CloseAgent(destination, agentID);
203 } 207 }
204 208
205 /// <summary>
206 /// Closes a child agents in a collection of regions. Does so asynchronously
207 /// so that the caller doesn't wait.
208 /// </summary>
209 /// <param name="agentID"></param>
210 /// <param name="regionslst"></param>
211 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 209 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
212 { 210 {
213 foreach (ulong handle in regionslst) 211 foreach (ulong handle in regionslst)
214 { 212 {
215 SendCloseChildAgent(agentID, handle); 213 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
214 d.BeginInvoke(agentID, handle,
215 SendCloseChildAgentCompleted,
216 d);
216 } 217 }
217 } 218 }
218 219
219 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 220 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
220 { 221 {
221 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 222 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
222 } 223 }
223 } 224 }
224} \ No newline at end of file 225}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 67eb0fe..f6f6a1a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes
41{ 41{
42 public delegate void PhysicsCrash(); 42 public delegate void PhysicsCrash();
43 43
44 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
45
46 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
49
44 /// <summary> 50 /// <summary>
45 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components 51 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
46 /// should be migrated out over time. 52 /// should be migrated out over time.
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes
54 protected internal event PhysicsCrash UnRecoverableError; 60 protected internal event PhysicsCrash UnRecoverableError;
55 private PhysicsCrash handlerPhysicsCrash = null; 61 private PhysicsCrash handlerPhysicsCrash = null;
56 62
63 public event AttachToBackupDelegate OnAttachToBackup;
64 public event DetachFromBackupDelegate OnDetachFromBackup;
65 public event ChangedBackupDelegate OnChangeBackup;
66
57 #endregion 67 #endregion
58 68
59 #region Fields 69 #region Fields
60 70
61 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
62 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
63 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
64 74
@@ -123,13 +133,18 @@ namespace OpenSim.Region.Framework.Scenes
123 133
124 protected internal void Close() 134 protected internal void Close()
125 { 135 {
126 lock (m_presenceLock) 136 m_scenePresencesLock.EnterWriteLock();
137 try
127 { 138 {
128 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
129 List<ScenePresence> newlist = new List<ScenePresence>(); 140 List<ScenePresence> newlist = new List<ScenePresence>();
130 m_scenePresenceMap = newmap; 141 m_scenePresenceMap = newmap;
131 m_scenePresenceArray = newlist; 142 m_scenePresenceArray = newlist;
132 } 143 }
144 finally
145 {
146 m_scenePresencesLock.ExitWriteLock();
147 }
133 148
134 lock (SceneObjectGroupsByFullID) 149 lock (SceneObjectGroupsByFullID)
135 SceneObjectGroupsByFullID.Clear(); 150 SceneObjectGroupsByFullID.Clear();
@@ -250,6 +265,33 @@ namespace OpenSim.Region.Framework.Scenes
250 protected internal bool AddRestoredSceneObject( 265 protected internal bool AddRestoredSceneObject(
251 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 266 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
252 { 267 {
268 if (!m_parentScene.CombineRegions)
269 {
270 // KF: Check for out-of-region, move inside and make static.
271 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
272 sceneObject.RootPart.GroupPosition.Y,
273 sceneObject.RootPart.GroupPosition.Z);
274 if (!(((sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) && (sceneObject.RootPart.Shape.State != 0))) && (npos.X < 0.0 || npos.Y < 0.0 || npos.Z < 0.0 ||
275 npos.X > Constants.RegionSize ||
276 npos.Y > Constants.RegionSize))
277 {
278 if (npos.X < 0.0) npos.X = 1.0f;
279 if (npos.Y < 0.0) npos.Y = 1.0f;
280 if (npos.Z < 0.0) npos.Z = 0.0f;
281 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
282 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
283
284 foreach (SceneObjectPart part in sceneObject.Parts)
285 {
286 part.GroupPosition = npos;
287 }
288 sceneObject.RootPart.Velocity = Vector3.Zero;
289 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
290 sceneObject.RootPart.Acceleration = Vector3.Zero;
291 sceneObject.RootPart.Velocity = Vector3.Zero;
292 }
293 }
294
253 if (attachToBackup && (!alreadyPersisted)) 295 if (attachToBackup && (!alreadyPersisted))
254 { 296 {
255 sceneObject.ForceInventoryPersistence(); 297 sceneObject.ForceInventoryPersistence();
@@ -340,6 +382,11 @@ namespace OpenSim.Region.Framework.Scenes
340 /// </returns> 382 /// </returns>
341 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 383 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
342 { 384 {
385 if (sceneObject == null)
386 {
387 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
388 return false;
389 }
343 if (sceneObject.UUID == UUID.Zero) 390 if (sceneObject.UUID == UUID.Zero)
344 { 391 {
345 m_log.ErrorFormat( 392 m_log.ErrorFormat(
@@ -474,6 +521,30 @@ namespace OpenSim.Region.Framework.Scenes
474 m_updateList[obj.UUID] = obj; 521 m_updateList[obj.UUID] = obj;
475 } 522 }
476 523
524 public void FireAttachToBackup(SceneObjectGroup obj)
525 {
526 if (OnAttachToBackup != null)
527 {
528 OnAttachToBackup(obj);
529 }
530 }
531
532 public void FireDetachFromBackup(SceneObjectGroup obj)
533 {
534 if (OnDetachFromBackup != null)
535 {
536 OnDetachFromBackup(obj);
537 }
538 }
539
540 public void FireChangeBackup(SceneObjectGroup obj)
541 {
542 if (OnChangeBackup != null)
543 {
544 OnChangeBackup(obj);
545 }
546 }
547
477 /// <summary> 548 /// <summary>
478 /// Process all pending updates 549 /// Process all pending updates
479 /// </summary> 550 /// </summary>
@@ -591,7 +662,8 @@ namespace OpenSim.Region.Framework.Scenes
591 662
592 Entities[presence.UUID] = presence; 663 Entities[presence.UUID] = presence;
593 664
594 lock (m_presenceLock) 665 m_scenePresencesLock.EnterWriteLock();
666 try
595 { 667 {
596 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 668 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
597 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 669 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -615,6 +687,10 @@ namespace OpenSim.Region.Framework.Scenes
615 m_scenePresenceMap = newmap; 687 m_scenePresenceMap = newmap;
616 m_scenePresenceArray = newlist; 688 m_scenePresenceArray = newlist;
617 } 689 }
690 finally
691 {
692 m_scenePresencesLock.ExitWriteLock();
693 }
618 } 694 }
619 695
620 /// <summary> 696 /// <summary>
@@ -629,7 +705,8 @@ namespace OpenSim.Region.Framework.Scenes
629 agentID); 705 agentID);
630 } 706 }
631 707
632 lock (m_presenceLock) 708 m_scenePresencesLock.EnterWriteLock();
709 try
633 { 710 {
634 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 711 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
635 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 712 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -651,6 +728,10 @@ namespace OpenSim.Region.Framework.Scenes
651 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 728 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
652 } 729 }
653 } 730 }
731 finally
732 {
733 m_scenePresencesLock.ExitWriteLock();
734 }
654 } 735 }
655 736
656 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 737 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1183,6 +1264,25 @@ namespace OpenSim.Region.Framework.Scenes
1183 1264
1184 #region Client Event handlers 1265 #region Client Event handlers
1185 1266
1267 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1268 {
1269 SceneObjectPart part = GetSceneObjectPart(localID);
1270 ObjectChangeData data = (ObjectChangeData)odata;
1271
1272 if (part != null)
1273 {
1274 SceneObjectGroup grp = part.ParentGroup;
1275 if (grp != null)
1276 {
1277 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1278 {
1279 part.StoreUndoState(data.change); // lets test only saving what we changed
1280 grp.doChangeObject(part, (ObjectChangeData)data);
1281 }
1282 }
1283 }
1284 }
1285
1186 /// <summary> 1286 /// <summary>
1187 /// Update the scale of an individual prim. 1287 /// Update the scale of an individual prim.
1188 /// </summary> 1288 /// </summary>
@@ -1197,7 +1297,17 @@ namespace OpenSim.Region.Framework.Scenes
1197 { 1297 {
1198 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1298 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1199 { 1299 {
1300 bool physbuild = false;
1301 if (part.ParentGroup.RootPart.PhysActor != null)
1302 {
1303 part.ParentGroup.RootPart.PhysActor.Building = true;
1304 physbuild = true;
1305 }
1306
1200 part.Resize(scale); 1307 part.Resize(scale);
1308
1309 if (physbuild)
1310 part.ParentGroup.RootPart.PhysActor.Building = false;
1201 } 1311 }
1202 } 1312 }
1203 } 1313 }
@@ -1209,7 +1319,17 @@ namespace OpenSim.Region.Framework.Scenes
1209 { 1319 {
1210 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1320 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1211 { 1321 {
1322 bool physbuild = false;
1323 if (group.RootPart.PhysActor != null)
1324 {
1325 group.RootPart.PhysActor.Building = true;
1326 physbuild = true;
1327 }
1328
1212 group.GroupResize(scale); 1329 group.GroupResize(scale);
1330
1331 if (physbuild)
1332 group.RootPart.PhysActor.Building = false;
1213 } 1333 }
1214 } 1334 }
1215 } 1335 }
@@ -1337,8 +1457,13 @@ namespace OpenSim.Region.Framework.Scenes
1337 { 1457 {
1338 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1458 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1339 { 1459 {
1340 if (m_parentScene.AttachmentsModule != null) 1460 // Set the new attachment point data in the object
1341 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1461 byte attachmentPoint = group.GetAttachmentPoint();
1462 group.UpdateGroupPosition(pos);
1463 group.IsAttachment = false;
1464 group.AbsolutePosition = group.RootPart.AttachedPos;
1465 group.AttachmentPoint = attachmentPoint;
1466 group.HasGroupChanged = true;
1342 } 1467 }
1343 else 1468 else
1344 { 1469 {
@@ -1386,7 +1511,7 @@ namespace OpenSim.Region.Framework.Scenes
1386 /// <param name="SetPhantom"></param> 1511 /// <param name="SetPhantom"></param>
1387 /// <param name="remoteClient"></param> 1512 /// <param name="remoteClient"></param>
1388 protected internal void UpdatePrimFlags( 1513 protected internal void UpdatePrimFlags(
1389 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) 1514 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient)
1390 { 1515 {
1391 SceneObjectGroup group = GetGroupByPrim(localID); 1516 SceneObjectGroup group = GetGroupByPrim(localID);
1392 if (group != null) 1517 if (group != null)
@@ -1394,7 +1519,28 @@ namespace OpenSim.Region.Framework.Scenes
1394 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1519 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1395 { 1520 {
1396 // VolumeDetect can't be set via UI and will always be off when a change is made there 1521 // VolumeDetect can't be set via UI and will always be off when a change is made there
1397 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); 1522 // now only change volume dtc if phantom off
1523
1524 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1525 {
1526 bool vdtc;
1527 if (SetPhantom) // if phantom keep volumedtc
1528 vdtc = group.RootPart.VolumeDetectActive;
1529 else // else turn it off
1530 vdtc = false;
1531
1532 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc);
1533 }
1534 else
1535 {
1536 SceneObjectPart part = GetSceneObjectPart(localID);
1537 if (part != null)
1538 {
1539 part.UpdateExtraPhysics(PhysData);
1540 if (part.UpdatePhysRequired)
1541 remoteClient.SendPartPhysicsProprieties(part);
1542 }
1543 }
1398 } 1544 }
1399 } 1545 }
1400 } 1546 }
@@ -1538,6 +1684,7 @@ namespace OpenSim.Region.Framework.Scenes
1538 { 1684 {
1539 part.Material = Convert.ToByte(material); 1685 part.Material = Convert.ToByte(material);
1540 group.HasGroupChanged = true; 1686 group.HasGroupChanged = true;
1687 remoteClient.SendPartPhysicsProprieties(part);
1541 } 1688 }
1542 } 1689 }
1543 } 1690 }
@@ -1602,6 +1749,12 @@ namespace OpenSim.Region.Framework.Scenes
1602 /// <param name="childPrims"></param> 1749 /// <param name="childPrims"></param>
1603 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1750 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1604 { 1751 {
1752 if (root.KeyframeMotion != null)
1753 {
1754 root.KeyframeMotion.Stop();
1755 root.KeyframeMotion = null;
1756 }
1757
1605 SceneObjectGroup parentGroup = root.ParentGroup; 1758 SceneObjectGroup parentGroup = root.ParentGroup;
1606 if (parentGroup == null) return; 1759 if (parentGroup == null) return;
1607 1760
@@ -1610,8 +1763,11 @@ namespace OpenSim.Region.Framework.Scenes
1610 return; 1763 return;
1611 1764
1612 Monitor.Enter(m_updateLock); 1765 Monitor.Enter(m_updateLock);
1766
1613 try 1767 try
1614 { 1768 {
1769 parentGroup.areUpdatesSuspended = true;
1770
1615 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1771 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1616 1772
1617 // We do this in reverse to get the link order of the prims correct 1773 // We do this in reverse to get the link order of the prims correct
@@ -1626,9 +1782,13 @@ namespace OpenSim.Region.Framework.Scenes
1626 // Make sure no child prim is set for sale 1782 // Make sure no child prim is set for sale
1627 // So that, on delink, no prims are unwittingly 1783 // So that, on delink, no prims are unwittingly
1628 // left for sale and sold off 1784 // left for sale and sold off
1629 child.RootPart.ObjectSaleType = 0; 1785
1630 child.RootPart.SalePrice = 10; 1786 if (child != null)
1631 childGroups.Add(child); 1787 {
1788 child.RootPart.ObjectSaleType = 0;
1789 child.RootPart.SalePrice = 10;
1790 childGroups.Add(child);
1791 }
1632 } 1792 }
1633 1793
1634 foreach (SceneObjectGroup child in childGroups) 1794 foreach (SceneObjectGroup child in childGroups)
@@ -1655,6 +1815,16 @@ namespace OpenSim.Region.Framework.Scenes
1655 } 1815 }
1656 finally 1816 finally
1657 { 1817 {
1818 lock (SceneObjectGroupsByLocalPartID)
1819 {
1820 foreach (SceneObjectPart part in parentGroup.Parts)
1821 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1822 }
1823
1824 parentGroup.areUpdatesSuspended = false;
1825 parentGroup.HasGroupChanged = true;
1826 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1827 parentGroup.ScheduleGroupForFullUpdate();
1658 Monitor.Exit(m_updateLock); 1828 Monitor.Exit(m_updateLock);
1659 } 1829 }
1660 } 1830 }
@@ -1677,6 +1847,11 @@ namespace OpenSim.Region.Framework.Scenes
1677 { 1847 {
1678 if (part != null) 1848 if (part != null)
1679 { 1849 {
1850 if (part.KeyframeMotion != null)
1851 {
1852 part.KeyframeMotion.Stop();
1853 part.KeyframeMotion = null;
1854 }
1680 if (part.ParentGroup.PrimCount != 1) // Skip single 1855 if (part.ParentGroup.PrimCount != 1) // Skip single
1681 { 1856 {
1682 if (part.LinkNum < 2) // Root 1857 if (part.LinkNum < 2) // Root
@@ -1691,21 +1866,24 @@ namespace OpenSim.Region.Framework.Scenes
1691 1866
1692 SceneObjectGroup group = part.ParentGroup; 1867 SceneObjectGroup group = part.ParentGroup;
1693 if (!affectedGroups.Contains(group)) 1868 if (!affectedGroups.Contains(group))
1869 {
1870 group.areUpdatesSuspended = true;
1694 affectedGroups.Add(group); 1871 affectedGroups.Add(group);
1872 }
1695 } 1873 }
1696 } 1874 }
1697 } 1875 }
1698 1876
1699 foreach (SceneObjectPart child in childParts) 1877 if (childParts.Count > 0)
1700 { 1878 {
1701 // Unlink all child parts from their groups 1879 foreach (SceneObjectPart child in childParts)
1702 // 1880 {
1703 child.ParentGroup.DelinkFromGroup(child, true); 1881 // Unlink all child parts from their groups
1704 1882 //
1705 // These are not in affected groups and will not be 1883 child.ParentGroup.DelinkFromGroup(child, true);
1706 // handled further. Do the honors here. 1884 child.ParentGroup.HasGroupChanged = true;
1707 child.ParentGroup.HasGroupChanged = true; 1885 child.ParentGroup.ScheduleGroupForFullUpdate();
1708 child.ParentGroup.ScheduleGroupForFullUpdate(); 1886 }
1709 } 1887 }
1710 1888
1711 foreach (SceneObjectPart root in rootParts) 1889 foreach (SceneObjectPart root in rootParts)
@@ -1715,56 +1893,68 @@ namespace OpenSim.Region.Framework.Scenes
1715 // However, editing linked parts and unlinking may be different 1893 // However, editing linked parts and unlinking may be different
1716 // 1894 //
1717 SceneObjectGroup group = root.ParentGroup; 1895 SceneObjectGroup group = root.ParentGroup;
1896 group.areUpdatesSuspended = true;
1718 1897
1719 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1898 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1720 int numChildren = newSet.Count; 1899 int numChildren = newSet.Count;
1721 1900
1901 if (numChildren == 1)
1902 break;
1903
1722 // If there are prims left in a link set, but the root is 1904 // If there are prims left in a link set, but the root is
1723 // slated for unlink, we need to do this 1905 // slated for unlink, we need to do this
1906 // Unlink the remaining set
1724 // 1907 //
1725 if (numChildren != 1) 1908 bool sendEventsToRemainder = true;
1726 { 1909 if (numChildren > 1)
1727 // Unlink the remaining set 1910 sendEventsToRemainder = false;
1728 //
1729 bool sendEventsToRemainder = true;
1730 if (numChildren > 1)
1731 sendEventsToRemainder = false;
1732 1911
1733 foreach (SceneObjectPart p in newSet) 1912 foreach (SceneObjectPart p in newSet)
1913 {
1914 if (p != group.RootPart)
1734 { 1915 {
1735 if (p != group.RootPart) 1916 group.DelinkFromGroup(p, sendEventsToRemainder);
1736 group.DelinkFromGroup(p, sendEventsToRemainder); 1917 if (numChildren > 2)
1918 {
1919 p.ParentGroup.areUpdatesSuspended = true;
1920 }
1921 else
1922 {
1923 p.ParentGroup.HasGroupChanged = true;
1924 p.ParentGroup.ScheduleGroupForFullUpdate();
1925 }
1737 } 1926 }
1927 }
1738 1928
1739 // If there is more than one prim remaining, we 1929 // If there is more than one prim remaining, we
1740 // need to re-link 1930 // need to re-link
1931 //
1932 if (numChildren > 2)
1933 {
1934 // Remove old root
1741 // 1935 //
1742 if (numChildren > 2) 1936 if (newSet.Contains(root))
1937 newSet.Remove(root);
1938
1939 // Preserve link ordering
1940 //
1941 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1743 { 1942 {
1744 // Remove old root 1943 return a.LinkNum.CompareTo(b.LinkNum);
1745 // 1944 });
1746 if (newSet.Contains(root))
1747 newSet.Remove(root);
1748
1749 // Preserve link ordering
1750 //
1751 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1752 {
1753 return a.LinkNum.CompareTo(b.LinkNum);
1754 });
1755 1945
1756 // Determine new root 1946 // Determine new root
1757 // 1947 //
1758 SceneObjectPart newRoot = newSet[0]; 1948 SceneObjectPart newRoot = newSet[0];
1759 newSet.RemoveAt(0); 1949 newSet.RemoveAt(0);
1760 1950
1761 foreach (SceneObjectPart newChild in newSet) 1951 foreach (SceneObjectPart newChild in newSet)
1762 newChild.ClearUpdateSchedule(); 1952 newChild.ClearUpdateSchedule();
1763 1953
1764 LinkObjects(newRoot, newSet); 1954 newRoot.ParentGroup.areUpdatesSuspended = true;
1765 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1955 LinkObjects(newRoot, newSet);
1766 affectedGroups.Add(newRoot.ParentGroup); 1956 if (!affectedGroups.Contains(newRoot.ParentGroup))
1767 } 1957 affectedGroups.Add(newRoot.ParentGroup);
1768 } 1958 }
1769 } 1959 }
1770 1960
@@ -1772,8 +1962,14 @@ namespace OpenSim.Region.Framework.Scenes
1772 // 1962 //
1773 foreach (SceneObjectGroup g in affectedGroups) 1963 foreach (SceneObjectGroup g in affectedGroups)
1774 { 1964 {
1965 // Child prims that have been unlinked and deleted will
1966 // return unless the root is deleted. This will remove them
1967 // from the database. They will be rewritten immediately,
1968 // minus the rows for the unlinked child prims.
1969 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1775 g.TriggerScriptChangedEvent(Changed.LINK); 1970 g.TriggerScriptChangedEvent(Changed.LINK);
1776 g.HasGroupChanged = true; // Persist 1971 g.HasGroupChanged = true; // Persist
1972 g.areUpdatesSuspended = false;
1777 g.ScheduleGroupForFullUpdate(); 1973 g.ScheduleGroupForFullUpdate();
1778 } 1974 }
1779 } 1975 }
@@ -1875,9 +2071,6 @@ namespace OpenSim.Region.Framework.Scenes
1875 child.ApplyNextOwnerPermissions(); 2071 child.ApplyNextOwnerPermissions();
1876 } 2072 }
1877 } 2073 }
1878
1879 copy.RootPart.ObjectSaleType = 0;
1880 copy.RootPart.SalePrice = 10;
1881 } 2074 }
1882 2075
1883 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2076 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index d73a959..e4eaf3a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -356,7 +356,7 @@ namespace OpenSim.Region.Framework.Scenes
356 356
357 public bool TrySetCurrentScene(UUID regionID) 357 public bool TrySetCurrentScene(UUID regionID)
358 { 358 {
359 m_log.Debug("Searching for Region: '" + regionID + "'"); 359// m_log.Debug("Searching for Region: '" + regionID + "'");
360 360
361 lock (m_localScenes) 361 lock (m_localScenes)
362 { 362 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 10012d0..2effa25 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -69,10 +69,6 @@ namespace OpenSim.Region.Framework.Scenes
69 /// <summary> 69 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 70 /// Stop the scripts contained in all the prims in this group
71 /// </summary> 71 /// </summary>
72 /// <param name="sceneObjectBeingDeleted">
73 /// Should be true if these scripts are being removed because the scene
74 /// object is being deleted. This will prevent spurious updates to the client.
75 /// </param>
76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
77 { 73 {
78 SceneObjectPart[] parts = m_parts.GetArray(); 74 SceneObjectPart[] parts = m_parts.GetArray();
@@ -227,6 +223,11 @@ namespace OpenSim.Region.Framework.Scenes
227 223
228 public uint GetEffectivePermissions() 224 public uint GetEffectivePermissions()
229 { 225 {
226 return GetEffectivePermissions(false);
227 }
228
229 public uint GetEffectivePermissions(bool useBase)
230 {
230 uint perms=(uint)(PermissionMask.Modify | 231 uint perms=(uint)(PermissionMask.Modify |
231 PermissionMask.Copy | 232 PermissionMask.Copy |
232 PermissionMask.Move | 233 PermissionMask.Move |
@@ -238,7 +239,10 @@ namespace OpenSim.Region.Framework.Scenes
238 for (int i = 0; i < parts.Length; i++) 239 for (int i = 0; i < parts.Length; i++)
239 { 240 {
240 SceneObjectPart part = parts[i]; 241 SceneObjectPart part = parts[i];
241 ownerMask &= part.OwnerMask; 242 if (useBase)
243 ownerMask &= part.BaseMask;
244 else
245 ownerMask &= part.OwnerMask;
242 perms &= part.Inventory.MaskEffectivePermissions(); 246 perms &= part.Inventory.MaskEffectivePermissions();
243 } 247 }
244 248
@@ -380,6 +384,9 @@ namespace OpenSim.Region.Framework.Scenes
380 384
381 public void ResumeScripts() 385 public void ResumeScripts()
382 { 386 {
387 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
388 return;
389
383 SceneObjectPart[] parts = m_parts.GetArray(); 390 SceneObjectPart[] parts = m_parts.GetArray();
384 for (int i = 0; i < parts.Length; i++) 391 for (int i = 0; i < parts.Length; i++)
385 parts[i].Inventory.ResumeScripts(); 392 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 8e786c1..cb0a57a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,11 +24,12 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -42,6 +43,7 @@ using OpenSim.Region.Framework.Scenes.Serialization;
42 43
43namespace OpenSim.Region.Framework.Scenes 44namespace OpenSim.Region.Framework.Scenes
44{ 45{
46
45 [Flags] 47 [Flags]
46 public enum scriptEvents 48 public enum scriptEvents
47 { 49 {
@@ -105,8 +107,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 107 /// since the group's last persistent backup
106 /// </summary> 108 /// </summary>
107 private bool m_hasGroupChanged = false; 109 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 110 private long timeFirstChanged = 0;
109 private long timeLastChanged; 111 private long timeLastChanged = 0;
112 private long m_maxPersistTime = 0;
113 private long m_minPersistTime = 0;
114 private Random m_rand;
115 private bool m_suspendUpdates;
116 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
117
118 public bool areUpdatesSuspended
119 {
120 get
121 {
122 return m_suspendUpdates;
123 }
124 set
125 {
126 m_suspendUpdates = value;
127 if (!value)
128 {
129 QueueForUpdateCheck();
130 }
131 }
132 }
110 133
111 public bool HasGroupChanged 134 public bool HasGroupChanged
112 { 135 {
@@ -114,9 +137,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 137 {
115 if (value) 138 if (value)
116 { 139 {
140 if (m_isBackedUp)
141 {
142 m_scene.SceneGraph.FireChangeBackup(this);
143 }
117 timeLastChanged = DateTime.Now.Ticks; 144 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 145 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 146 timeFirstChanged = DateTime.Now.Ticks;
147 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
148 {
149 if (m_rand == null)
150 {
151 byte[] val = new byte[16];
152 m_rootPart.UUID.ToBytes(val, 0);
153 m_rand = new Random(BitConverter.ToInt32(val, 0));
154 }
155
156 if (m_scene.GetRootAgentCount() == 0)
157 {
158 //If the region is empty, this change has been made by an automated process
159 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
160
161 float factor = 1.5f + (float)(m_rand.NextDouble());
162 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
163 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
164 }
165 else
166 {
167 //If the region is not empty, we want to obey the minimum and maximum persist times
168 //but add a random factor so we stagger the object persistance a little
169 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
170 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
171 }
172 }
120 } 173 }
121 m_hasGroupChanged = value; 174 m_hasGroupChanged = value;
122 175
@@ -131,7 +184,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 184 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
132 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 185 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 186 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 187 public bool HasGroupChangedDueToDelink { get; set; }
135 188
136 private bool isTimeToPersist() 189 private bool isTimeToPersist()
137 { 190 {
@@ -141,8 +194,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 194 return false;
142 if (m_scene.ShuttingDown) 195 if (m_scene.ShuttingDown)
143 return true; 196 return true;
197
198 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
199 {
200 m_maxPersistTime = m_scene.m_persistAfter;
201 m_minPersistTime = m_scene.m_dontPersistBefore;
202 }
203
144 long currentTime = DateTime.Now.Ticks; 204 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 205
206 if (timeLastChanged == 0) timeLastChanged = currentTime;
207 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
208
209 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 210 return true;
147 return false; 211 return false;
148 } 212 }
@@ -245,10 +309,10 @@ namespace OpenSim.Region.Framework.Scenes
245 309
246 private bool m_scriptListens_atTarget; 310 private bool m_scriptListens_atTarget;
247 private bool m_scriptListens_notAtTarget; 311 private bool m_scriptListens_notAtTarget;
248
249 private bool m_scriptListens_atRotTarget; 312 private bool m_scriptListens_atRotTarget;
250 private bool m_scriptListens_notAtRotTarget; 313 private bool m_scriptListens_notAtRotTarget;
251 314
315 public bool m_dupeInProgress = false;
252 internal Dictionary<UUID, string> m_savedScriptState; 316 internal Dictionary<UUID, string> m_savedScriptState;
253 317
254 #region Properties 318 #region Properties
@@ -285,6 +349,16 @@ namespace OpenSim.Region.Framework.Scenes
285 get { return m_parts.Count; } 349 get { return m_parts.Count; }
286 } 350 }
287 351
352// protected Quaternion m_rotation = Quaternion.Identity;
353//
354// public virtual Quaternion Rotation
355// {
356// get { return m_rotation; }
357// set {
358// m_rotation = value;
359// }
360// }
361
288 public Quaternion GroupRotation 362 public Quaternion GroupRotation
289 { 363 {
290 get { return m_rootPart.RotationOffset; } 364 get { return m_rootPart.RotationOffset; }
@@ -404,14 +478,99 @@ namespace OpenSim.Region.Framework.Scenes
404 478
405 if (Scene != null) 479 if (Scene != null)
406 { 480 {
407 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 481 // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
408 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 482 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
483 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
484 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W)
485 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S))
409 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 486 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
410 { 487 {
411 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 488 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
489 uint x = 0;
490 uint y = 0;
491 string version = String.Empty;
492 Vector3 newpos = Vector3.Zero;
493 OpenSim.Services.Interfaces.GridRegion destination = null;
494
495 bool canCross = true;
496 foreach (ScenePresence av in m_linkedAvatars)
497 {
498 // We need to cross these agents. First, let's find
499 // out if any of them can't cross for some reason.
500 // We have to deny the crossing entirely if any
501 // of them are banned. Alternatively, we could
502 // unsit banned agents....
503
504
505 // We set the avatar position as being the object
506 // position to get the region to send to
507 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
508 {
509 canCross = false;
510 break;
511 }
512
513 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
514 }
515
516 if (canCross)
517 {
518 // We unparent the SP quietly so that it won't
519 // be made to stand up
520 foreach (ScenePresence av in m_linkedAvatars)
521 {
522 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
523 if (parentPart != null)
524 av.ParentUUID = parentPart.UUID;
525
526 av.ParentID = 0;
527 }
528
529 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
530
531 // Normalize
532 if (val.X >= Constants.RegionSize)
533 val.X -= Constants.RegionSize;
534 if (val.Y >= Constants.RegionSize)
535 val.Y -= Constants.RegionSize;
536 if (val.X < 0)
537 val.X += Constants.RegionSize;
538 if (val.Y < 0)
539 val.Y += Constants.RegionSize;
540
541 // If it's deleted, crossing was successful
542 if (IsDeleted)
543 {
544 foreach (ScenePresence av in m_linkedAvatars)
545 {
546 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
547
548 av.IsInTransit = true;
549
550 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
551 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
552 }
553
554 return;
555 }
556 }
557 else if (RootPart.PhysActor != null)
558 {
559 RootPart.PhysActor.CrossingFailure();
560 }
561
562 Vector3 oldp = AbsolutePosition;
563 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
564 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
565 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
412 } 566 }
413 } 567 }
414 568/* don't see the need but worse don't see where is restored to false if things stay in
569 foreach (SceneObjectPart part in m_parts.GetArray())
570 {
571 part.IgnoreUndoUpdate = true;
572 }
573 */
415 if (RootPart.GetStatusSandbox()) 574 if (RootPart.GetStatusSandbox())
416 { 575 {
417 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 576 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -425,10 +584,30 @@ namespace OpenSim.Region.Framework.Scenes
425 return; 584 return;
426 } 585 }
427 } 586 }
428
429 SceneObjectPart[] parts = m_parts.GetArray(); 587 SceneObjectPart[] parts = m_parts.GetArray();
430 for (int i = 0; i < parts.Length; i++) 588 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
431 parts[i].GroupPosition = val; 589 if (m_dupeInProgress)
590 triggerScriptEvent = false;
591 foreach (SceneObjectPart part in parts)
592 {
593 part.GroupPosition = val;
594 if (triggerScriptEvent)
595 part.TriggerScriptChangedEvent(Changed.POSITION);
596 }
597 if (!m_dupeInProgress)
598 {
599 foreach (ScenePresence av in m_linkedAvatars)
600 {
601 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
602 if (p != null && m_parts.TryGetValue(p.UUID, out p))
603 {
604 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
605 av.AbsolutePosition += offset;
606 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
607 av.SendAvatarDataToAllAgents();
608 }
609 }
610 }
432 611
433 //if (m_rootPart.PhysActor != null) 612 //if (m_rootPart.PhysActor != null)
434 //{ 613 //{
@@ -443,6 +622,29 @@ namespace OpenSim.Region.Framework.Scenes
443 } 622 }
444 } 623 }
445 624
625 public override Vector3 Velocity
626 {
627 get { return RootPart.Velocity; }
628 set { RootPart.Velocity = value; }
629 }
630
631 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
632 {
633 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
634 ScenePresence agent = icon.EndInvoke(iar);
635
636 //// If the cross was successful, this agent is a child agent
637 //if (agent.IsChildAgent)
638 // agent.Reset();
639 //else // Not successful
640 // agent.RestoreInCurrentScene();
641
642 // In any case
643 agent.IsInTransit = false;
644
645 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
646 }
647
446 public override uint LocalId 648 public override uint LocalId
447 { 649 {
448 get { return m_rootPart.LocalId; } 650 get { return m_rootPart.LocalId; }
@@ -540,6 +742,8 @@ namespace OpenSim.Region.Framework.Scenes
540 childPa.Selected = value; 742 childPa.Selected = value;
541 } 743 }
542 } 744 }
745 if (RootPart.KeyframeMotion != null)
746 RootPart.KeyframeMotion.Selected = value;
543 } 747 }
544 } 748 }
545 749
@@ -617,6 +821,7 @@ namespace OpenSim.Region.Framework.Scenes
617 /// </summary> 821 /// </summary>
618 public SceneObjectGroup() 822 public SceneObjectGroup()
619 { 823 {
824
620 } 825 }
621 826
622 /// <summary> 827 /// <summary>
@@ -633,7 +838,7 @@ namespace OpenSim.Region.Framework.Scenes
633 /// Constructor. This object is added to the scene later via AttachToScene() 838 /// Constructor. This object is added to the scene later via AttachToScene()
634 /// </summary> 839 /// </summary>
635 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 840 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
636 { 841 {
637 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 842 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
638 } 843 }
639 844
@@ -669,6 +874,9 @@ namespace OpenSim.Region.Framework.Scenes
669 /// </summary> 874 /// </summary>
670 public virtual void AttachToBackup() 875 public virtual void AttachToBackup()
671 { 876 {
877 if (IsAttachment) return;
878 m_scene.SceneGraph.FireAttachToBackup(this);
879
672 if (InSceneBackup) 880 if (InSceneBackup)
673 { 881 {
674 //m_log.DebugFormat( 882 //m_log.DebugFormat(
@@ -711,6 +919,13 @@ namespace OpenSim.Region.Framework.Scenes
711 919
712 ApplyPhysics(); 920 ApplyPhysics();
713 921
922 if (RootPart.PhysActor != null)
923 RootPart.Force = RootPart.Force;
924 if (RootPart.PhysActor != null)
925 RootPart.Torque = RootPart.Torque;
926 if (RootPart.PhysActor != null)
927 RootPart.Buoyancy = RootPart.Buoyancy;
928
714 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 929 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
715 // for the same object with very different properties. The caller must schedule the update. 930 // for the same object with very different properties. The caller must schedule the update.
716 //ScheduleGroupForFullUpdate(); 931 //ScheduleGroupForFullUpdate();
@@ -726,6 +941,10 @@ namespace OpenSim.Region.Framework.Scenes
726 EntityIntersection result = new EntityIntersection(); 941 EntityIntersection result = new EntityIntersection();
727 942
728 SceneObjectPart[] parts = m_parts.GetArray(); 943 SceneObjectPart[] parts = m_parts.GetArray();
944
945 // Find closest hit here
946 float idist = float.MaxValue;
947
729 for (int i = 0; i < parts.Length; i++) 948 for (int i = 0; i < parts.Length; i++)
730 { 949 {
731 SceneObjectPart part = parts[i]; 950 SceneObjectPart part = parts[i];
@@ -740,11 +959,6 @@ namespace OpenSim.Region.Framework.Scenes
740 959
741 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 960 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
742 961
743 // This may need to be updated to the maximum draw distance possible..
744 // We might (and probably will) be checking for prim creation from other sims
745 // when the camera crosses the border.
746 float idist = Constants.RegionSize;
747
748 if (inter.HitTF) 962 if (inter.HitTF)
749 { 963 {
750 // We need to find the closest prim to return to the testcaller along the ray 964 // We need to find the closest prim to return to the testcaller along the ray
@@ -755,10 +969,11 @@ namespace OpenSim.Region.Framework.Scenes
755 result.obj = part; 969 result.obj = part;
756 result.normal = inter.normal; 970 result.normal = inter.normal;
757 result.distance = inter.distance; 971 result.distance = inter.distance;
972
973 idist = inter.distance;
758 } 974 }
759 } 975 }
760 } 976 }
761
762 return result; 977 return result;
763 } 978 }
764 979
@@ -770,25 +985,27 @@ namespace OpenSim.Region.Framework.Scenes
770 /// <returns></returns> 985 /// <returns></returns>
771 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 986 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
772 { 987 {
773 maxX = -256f; 988 maxX = float.MinValue;
774 maxY = -256f; 989 maxY = float.MinValue;
775 maxZ = -256f; 990 maxZ = float.MinValue;
776 minX = 256f; 991 minX = float.MaxValue;
777 minY = 256f; 992 minY = float.MaxValue;
778 minZ = 8192f; 993 minZ = float.MaxValue;
779 994
780 SceneObjectPart[] parts = m_parts.GetArray(); 995 SceneObjectPart[] parts = m_parts.GetArray();
781 for (int i = 0; i < parts.Length; i++) 996 foreach (SceneObjectPart part in parts)
782 { 997 {
783 SceneObjectPart part = parts[i];
784
785 Vector3 worldPos = part.GetWorldPosition(); 998 Vector3 worldPos = part.GetWorldPosition();
786 Vector3 offset = worldPos - AbsolutePosition; 999 Vector3 offset = worldPos - AbsolutePosition;
787 Quaternion worldRot; 1000 Quaternion worldRot;
788 if (part.ParentID == 0) 1001 if (part.ParentID == 0)
1002 {
789 worldRot = part.RotationOffset; 1003 worldRot = part.RotationOffset;
1004 }
790 else 1005 else
1006 {
791 worldRot = part.GetWorldRotation(); 1007 worldRot = part.GetWorldRotation();
1008 }
792 1009
793 Vector3 frontTopLeft; 1010 Vector3 frontTopLeft;
794 Vector3 frontTopRight; 1011 Vector3 frontTopRight;
@@ -800,6 +1017,8 @@ namespace OpenSim.Region.Framework.Scenes
800 Vector3 backBottomLeft; 1017 Vector3 backBottomLeft;
801 Vector3 backBottomRight; 1018 Vector3 backBottomRight;
802 1019
1020 // Vector3[] corners = new Vector3[8];
1021
803 Vector3 orig = Vector3.Zero; 1022 Vector3 orig = Vector3.Zero;
804 1023
805 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1024 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -834,6 +1053,38 @@ namespace OpenSim.Region.Framework.Scenes
834 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1053 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
835 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1054 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
836 1055
1056
1057
1058 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1059 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1060 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1061 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1062 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1063 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1064 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1065 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1066
1067 //for (int i = 0; i < 8; i++)
1068 //{
1069 // corners[i] = corners[i] * worldRot;
1070 // corners[i] += offset;
1071
1072 // if (corners[i].X > maxX)
1073 // maxX = corners[i].X;
1074 // if (corners[i].X < minX)
1075 // minX = corners[i].X;
1076
1077 // if (corners[i].Y > maxY)
1078 // maxY = corners[i].Y;
1079 // if (corners[i].Y < minY)
1080 // minY = corners[i].Y;
1081
1082 // if (corners[i].Z > maxZ)
1083 // maxZ = corners[i].Y;
1084 // if (corners[i].Z < minZ)
1085 // minZ = corners[i].Z;
1086 //}
1087
837 frontTopLeft = frontTopLeft * worldRot; 1088 frontTopLeft = frontTopLeft * worldRot;
838 frontTopRight = frontTopRight * worldRot; 1089 frontTopRight = frontTopRight * worldRot;
839 frontBottomLeft = frontBottomLeft * worldRot; 1090 frontBottomLeft = frontBottomLeft * worldRot;
@@ -855,6 +1106,15 @@ namespace OpenSim.Region.Framework.Scenes
855 backTopLeft += offset; 1106 backTopLeft += offset;
856 backTopRight += offset; 1107 backTopRight += offset;
857 1108
1109 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1110 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1111 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1112 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1113 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1114 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1115 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1116 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1117
858 if (frontTopRight.X > maxX) 1118 if (frontTopRight.X > maxX)
859 maxX = frontTopRight.X; 1119 maxX = frontTopRight.X;
860 if (frontTopLeft.X > maxX) 1120 if (frontTopLeft.X > maxX)
@@ -998,17 +1258,118 @@ namespace OpenSim.Region.Framework.Scenes
998 1258
999 #endregion 1259 #endregion
1000 1260
1261 public void GetResourcesCosts(SceneObjectPart apart,
1262 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1263 {
1264 // this information may need to be cached
1265
1266 float cost;
1267 float tmpcost;
1268
1269 bool ComplexCost = false;
1270
1271 SceneObjectPart p;
1272 SceneObjectPart[] parts;
1273
1274 lock (m_parts)
1275 {
1276 parts = m_parts.GetArray();
1277 }
1278
1279 int nparts = parts.Length;
1280
1281
1282 for (int i = 0; i < nparts; i++)
1283 {
1284 p = parts[i];
1285
1286 if (p.UsesComplexCost)
1287 {
1288 ComplexCost = true;
1289 break;
1290 }
1291 }
1292
1293 if (ComplexCost)
1294 {
1295 linksetResCost = 0;
1296 linksetPhysCost = 0;
1297 partCost = 0;
1298 partPhysCost = 0;
1299
1300 for (int i = 0; i < nparts; i++)
1301 {
1302 p = parts[i];
1303
1304 cost = p.StreamingCost;
1305 tmpcost = p.SimulationCost;
1306 if (tmpcost > cost)
1307 cost = tmpcost;
1308 tmpcost = p.PhysicsCost;
1309 if (tmpcost > cost)
1310 cost = tmpcost;
1311
1312 linksetPhysCost += tmpcost;
1313 linksetResCost += cost;
1314
1315 if (p == apart)
1316 {
1317 partCost = cost;
1318 partPhysCost = tmpcost;
1319 }
1320 }
1321 }
1322 else
1323 {
1324 partPhysCost = 1.0f;
1325 partCost = 1.0f;
1326 linksetResCost = (float)nparts;
1327 linksetPhysCost = linksetResCost;
1328 }
1329 }
1330
1331 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1332 {
1333 SceneObjectPart p;
1334 SceneObjectPart[] parts;
1335
1336 lock (m_parts)
1337 {
1338 parts = m_parts.GetArray();
1339 }
1340
1341 int nparts = parts.Length;
1342
1343 PhysCost = 0;
1344 StreamCost = 0;
1345 SimulCost = 0;
1346
1347 for (int i = 0; i < nparts; i++)
1348 {
1349 p = parts[i];
1350
1351 StreamCost += p.StreamingCost;
1352 SimulCost += p.SimulationCost;
1353 PhysCost += p.PhysicsCost;
1354 }
1355 }
1356
1001 public void SaveScriptedState(XmlTextWriter writer) 1357 public void SaveScriptedState(XmlTextWriter writer)
1002 { 1358 {
1359 SaveScriptedState(writer, false);
1360 }
1361
1362 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1363 {
1003 XmlDocument doc = new XmlDocument(); 1364 XmlDocument doc = new XmlDocument();
1004 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1365 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
1005 1366
1006 SceneObjectPart[] parts = m_parts.GetArray(); 1367 SceneObjectPart[] parts = m_parts.GetArray();
1007 for (int i = 0; i < parts.Length; i++) 1368 for (int i = 0; i < parts.Length; i++)
1008 { 1369 {
1009 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1370 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
1010 foreach (KeyValuePair<UUID, string> kvp in pstates) 1371 foreach (KeyValuePair<UUID, string> kvp in pstates)
1011 states.Add(kvp.Key, kvp.Value); 1372 states[kvp.Key] = kvp.Value;
1012 } 1373 }
1013 1374
1014 if (states.Count > 0) 1375 if (states.Count > 0)
@@ -1028,6 +1389,169 @@ namespace OpenSim.Region.Framework.Scenes
1028 } 1389 }
1029 1390
1030 /// <summary> 1391 /// <summary>
1392 /// Add the avatar to this linkset (avatar is sat).
1393 /// </summary>
1394 /// <param name="agentID"></param>
1395 public void AddAvatar(UUID agentID)
1396 {
1397 ScenePresence presence;
1398 if (m_scene.TryGetScenePresence(agentID, out presence))
1399 {
1400 if (!m_linkedAvatars.Contains(presence))
1401 {
1402 m_linkedAvatars.Add(presence);
1403 }
1404 }
1405 }
1406
1407 /// <summary>
1408 /// Delete the avatar from this linkset (avatar is unsat).
1409 /// </summary>
1410 /// <param name="agentID"></param>
1411 public void DeleteAvatar(UUID agentID)
1412 {
1413 ScenePresence presence;
1414 if (m_scene.TryGetScenePresence(agentID, out presence))
1415 {
1416 if (m_linkedAvatars.Contains(presence))
1417 {
1418 m_linkedAvatars.Remove(presence);
1419 }
1420 }
1421 }
1422
1423 /// <summary>
1424 /// Returns the list of linked presences (avatars sat on this group)
1425 /// </summary>
1426 /// <param name="agentID"></param>
1427 public List<ScenePresence> GetLinkedAvatars()
1428 {
1429 return m_linkedAvatars;
1430 }
1431
1432 /// <summary>
1433 /// Attach this scene object to the given avatar.
1434 /// </summary>
1435 /// <param name="agentID"></param>
1436 /// <param name="attachmentpoint"></param>
1437 /// <param name="AttachOffset"></param>
1438 private void AttachToAgent(
1439 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1440 {
1441 if (avatar != null)
1442 {
1443 // don't attach attachments to child agents
1444 if (avatar.IsChildAgent) return;
1445
1446 // Remove from database and parcel prim count
1447 m_scene.DeleteFromStorage(so.UUID);
1448 m_scene.EventManager.TriggerParcelPrimCountTainted();
1449
1450 so.AttachedAvatar = avatar.UUID;
1451
1452 if (so.RootPart.PhysActor != null)
1453 {
1454 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1455 so.RootPart.PhysActor = null;
1456 }
1457
1458 so.AbsolutePosition = attachOffset;
1459 so.RootPart.AttachedPos = attachOffset;
1460 so.IsAttachment = true;
1461 so.RootPart.SetParentLocalId(avatar.LocalId);
1462 so.AttachmentPoint = attachmentpoint;
1463
1464 avatar.AddAttachment(this);
1465
1466 if (!silent)
1467 {
1468 // Killing it here will cause the client to deselect it
1469 // It then reappears on the avatar, deselected
1470 // through the full update below
1471 //
1472 if (IsSelected)
1473 {
1474 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1475 }
1476
1477 IsSelected = false; // fudge....
1478 ScheduleGroupForFullUpdate();
1479 }
1480 }
1481 else
1482 {
1483 m_log.WarnFormat(
1484 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1485 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1486 }
1487 }
1488
1489 public byte GetAttachmentPoint()
1490 {
1491 return m_rootPart.Shape.State;
1492 }
1493
1494 public void DetachToGround()
1495 {
1496 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1497 if (avatar == null)
1498 return;
1499
1500 avatar.RemoveAttachment(this);
1501
1502 Vector3 detachedpos = new Vector3(127f,127f,127f);
1503 if (avatar == null)
1504 return;
1505
1506 detachedpos = avatar.AbsolutePosition;
1507 FromItemID = UUID.Zero;
1508
1509 AbsolutePosition = detachedpos;
1510 AttachedAvatar = UUID.Zero;
1511
1512 //SceneObjectPart[] parts = m_parts.GetArray();
1513 //for (int i = 0; i < parts.Length; i++)
1514 // parts[i].AttachedAvatar = UUID.Zero;
1515
1516 m_rootPart.SetParentLocalId(0);
1517 AttachmentPoint = (byte)0;
1518 // must check if buildind should be true or false here
1519 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1520 HasGroupChanged = true;
1521 RootPart.Rezzed = DateTime.Now;
1522 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1523 AttachToBackup();
1524 m_scene.EventManager.TriggerParcelPrimCountTainted();
1525 m_rootPart.ScheduleFullUpdate();
1526 m_rootPart.ClearUndoState();
1527 }
1528
1529 public void DetachToInventoryPrep()
1530 {
1531 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1532 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1533 if (avatar != null)
1534 {
1535 //detachedpos = avatar.AbsolutePosition;
1536 avatar.RemoveAttachment(this);
1537 }
1538
1539 AttachedAvatar = UUID.Zero;
1540
1541 /*SceneObjectPart[] parts = m_parts.GetArray();
1542 for (int i = 0; i < parts.Length; i++)
1543 parts[i].AttachedAvatar = UUID.Zero;*/
1544
1545 m_rootPart.SetParentLocalId(0);
1546 //m_rootPart.SetAttachmentPoint((byte)0);
1547 IsAttachment = false;
1548 AbsolutePosition = m_rootPart.AttachedPos;
1549 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1550 //AttachToBackup();
1551 //m_rootPart.ScheduleFullUpdate();
1552 }
1553
1554 /// <summary>
1031 /// 1555 ///
1032 /// </summary> 1556 /// </summary>
1033 /// <param name="part"></param> 1557 /// <param name="part"></param>
@@ -1077,7 +1601,10 @@ namespace OpenSim.Region.Framework.Scenes
1077 public void AddPart(SceneObjectPart part) 1601 public void AddPart(SceneObjectPart part)
1078 { 1602 {
1079 part.SetParent(this); 1603 part.SetParent(this);
1080 part.LinkNum = m_parts.Add(part.UUID, part); 1604 m_parts.Add(part.UUID, part);
1605
1606 part.LinkNum = m_parts.Count;
1607
1081 if (part.LinkNum == 2) 1608 if (part.LinkNum == 2)
1082 RootPart.LinkNum = 1; 1609 RootPart.LinkNum = 1;
1083 } 1610 }
@@ -1165,7 +1692,7 @@ namespace OpenSim.Region.Framework.Scenes
1165// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1692// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1166// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1693// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1167 1694
1168 part.StoreUndoState(); 1695// part.StoreUndoState();
1169 part.OnGrab(offsetPos, remoteClient); 1696 part.OnGrab(offsetPos, remoteClient);
1170 } 1697 }
1171 1698
@@ -1185,6 +1712,11 @@ namespace OpenSim.Region.Framework.Scenes
1185 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1712 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1186 public void DeleteGroupFromScene(bool silent) 1713 public void DeleteGroupFromScene(bool silent)
1187 { 1714 {
1715 // We need to keep track of this state in case this group is still queued for backup.
1716 IsDeleted = true;
1717
1718 DetachFromBackup();
1719
1188 SceneObjectPart[] parts = m_parts.GetArray(); 1720 SceneObjectPart[] parts = m_parts.GetArray();
1189 for (int i = 0; i < parts.Length; i++) 1721 for (int i = 0; i < parts.Length; i++)
1190 { 1722 {
@@ -1207,6 +1739,8 @@ namespace OpenSim.Region.Framework.Scenes
1207 } 1739 }
1208 }); 1740 });
1209 } 1741 }
1742
1743
1210 } 1744 }
1211 1745
1212 public void AddScriptLPS(int count) 1746 public void AddScriptLPS(int count)
@@ -1276,28 +1810,43 @@ namespace OpenSim.Region.Framework.Scenes
1276 /// </summary> 1810 /// </summary>
1277 public void ApplyPhysics() 1811 public void ApplyPhysics()
1278 { 1812 {
1279 // Apply physics to the root prim
1280 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1281
1282 // Apply physics to child prims
1283 SceneObjectPart[] parts = m_parts.GetArray(); 1813 SceneObjectPart[] parts = m_parts.GetArray();
1284 if (parts.Length > 1) 1814 if (parts.Length > 1)
1285 { 1815 {
1816 ResetChildPrimPhysicsPositions();
1817
1818 // Apply physics to the root prim
1819 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
1820
1821
1286 for (int i = 0; i < parts.Length; i++) 1822 for (int i = 0; i < parts.Length; i++)
1287 { 1823 {
1288 SceneObjectPart part = parts[i]; 1824 SceneObjectPart part = parts[i];
1289 if (part.LocalId != m_rootPart.LocalId) 1825 if (part.LocalId != m_rootPart.LocalId)
1290 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 1826 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1291 } 1827 }
1292
1293 // Hack to get the physics scene geometries in the right spot 1828 // Hack to get the physics scene geometries in the right spot
1294 ResetChildPrimPhysicsPositions(); 1829// ResetChildPrimPhysicsPositions();
1830 if (m_rootPart.PhysActor != null)
1831 {
1832 m_rootPart.PhysActor.Building = false;
1833 }
1834 }
1835 else
1836 {
1837 // Apply physics to the root prim
1838 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1295 } 1839 }
1296 } 1840 }
1297 1841
1298 public void SetOwnerId(UUID userId) 1842 public void SetOwnerId(UUID userId)
1299 { 1843 {
1300 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1844 ForEachPart(delegate(SceneObjectPart part)
1845 {
1846
1847 part.OwnerID = userId;
1848
1849 });
1301 } 1850 }
1302 1851
1303 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1852 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1329,11 +1878,17 @@ namespace OpenSim.Region.Framework.Scenes
1329 return; 1878 return;
1330 } 1879 }
1331 1880
1881 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1882 return;
1883
1332 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1884 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1333 // any exception propogate upwards. 1885 // any exception propogate upwards.
1334 try 1886 try
1335 { 1887 {
1336 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1888 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1889 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1890 m_scene.LoadingPrims) // Land may not be valid yet
1891
1337 { 1892 {
1338 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1893 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1339 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1894 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1360,6 +1915,7 @@ namespace OpenSim.Region.Framework.Scenes
1360 } 1915 }
1361 } 1916 }
1362 } 1917 }
1918
1363 } 1919 }
1364 1920
1365 if (m_scene.UseBackup && HasGroupChanged) 1921 if (m_scene.UseBackup && HasGroupChanged)
@@ -1367,10 +1923,30 @@ namespace OpenSim.Region.Framework.Scenes
1367 // don't backup while it's selected or you're asking for changes mid stream. 1923 // don't backup while it's selected or you're asking for changes mid stream.
1368 if (isTimeToPersist() || forcedBackup) 1924 if (isTimeToPersist() || forcedBackup)
1369 { 1925 {
1926 if (m_rootPart.PhysActor != null &&
1927 (!m_rootPart.PhysActor.IsPhysical))
1928 {
1929 // Possible ghost prim
1930 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1931 {
1932 foreach (SceneObjectPart part in m_parts.GetArray())
1933 {
1934 // Re-set physics actor positions and
1935 // orientations
1936 part.GroupPosition = m_rootPart.GroupPosition;
1937 }
1938 }
1939 }
1370// m_log.DebugFormat( 1940// m_log.DebugFormat(
1371// "[SCENE]: Storing {0}, {1} in {2}", 1941// "[SCENE]: Storing {0}, {1} in {2}",
1372// Name, UUID, m_scene.RegionInfo.RegionName); 1942// Name, UUID, m_scene.RegionInfo.RegionName);
1373 1943
1944 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
1945 {
1946 RootPart.Shape.State = 0;
1947 ScheduleGroupForFullUpdate();
1948 }
1949
1374 SceneObjectGroup backup_group = Copy(false); 1950 SceneObjectGroup backup_group = Copy(false);
1375 backup_group.RootPart.Velocity = RootPart.Velocity; 1951 backup_group.RootPart.Velocity = RootPart.Velocity;
1376 backup_group.RootPart.Acceleration = RootPart.Acceleration; 1952 backup_group.RootPart.Acceleration = RootPart.Acceleration;
@@ -1384,6 +1960,11 @@ namespace OpenSim.Region.Framework.Scenes
1384 1960
1385 backup_group.ForEachPart(delegate(SceneObjectPart part) 1961 backup_group.ForEachPart(delegate(SceneObjectPart part)
1386 { 1962 {
1963 if (part.KeyframeMotion != null)
1964 {
1965 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
1966 part.KeyframeMotion.UpdateSceneObject(this);
1967 }
1387 part.Inventory.ProcessInventoryBackup(datastore); 1968 part.Inventory.ProcessInventoryBackup(datastore);
1388 }); 1969 });
1389 1970
@@ -1436,6 +2017,7 @@ namespace OpenSim.Region.Framework.Scenes
1436 /// <returns></returns> 2017 /// <returns></returns>
1437 public SceneObjectGroup Copy(bool userExposed) 2018 public SceneObjectGroup Copy(bool userExposed)
1438 { 2019 {
2020 m_dupeInProgress = true;
1439 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 2021 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1440 dupe.m_isBackedUp = false; 2022 dupe.m_isBackedUp = false;
1441 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2023 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
@@ -1450,7 +2032,7 @@ namespace OpenSim.Region.Framework.Scenes
1450 // This is only necessary when userExposed is false! 2032 // This is only necessary when userExposed is false!
1451 2033
1452 bool previousAttachmentStatus = dupe.IsAttachment; 2034 bool previousAttachmentStatus = dupe.IsAttachment;
1453 2035
1454 if (!userExposed) 2036 if (!userExposed)
1455 dupe.IsAttachment = true; 2037 dupe.IsAttachment = true;
1456 2038
@@ -1468,11 +2050,11 @@ namespace OpenSim.Region.Framework.Scenes
1468 dupe.m_rootPart.TrimPermissions(); 2050 dupe.m_rootPart.TrimPermissions();
1469 2051
1470 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2052 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1471 2053
1472 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2054 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1473 { 2055 {
1474 return p1.LinkNum.CompareTo(p2.LinkNum); 2056 return p1.LinkNum.CompareTo(p2.LinkNum);
1475 } 2057 }
1476 ); 2058 );
1477 2059
1478 foreach (SceneObjectPart part in partList) 2060 foreach (SceneObjectPart part in partList)
@@ -1482,41 +2064,53 @@ namespace OpenSim.Region.Framework.Scenes
1482 { 2064 {
1483 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2065 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1484 newPart.LinkNum = part.LinkNum; 2066 newPart.LinkNum = part.LinkNum;
1485 } 2067 if (userExposed)
2068 newPart.ParentID = dupe.m_rootPart.LocalId;
2069 }
1486 else 2070 else
1487 { 2071 {
1488 newPart = dupe.m_rootPart; 2072 newPart = dupe.m_rootPart;
1489 } 2073 }
2074/*
2075 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2076 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1490 2077
1491 // Need to duplicate the physics actor as well 2078 // Need to duplicate the physics actor as well
1492 PhysicsActor originalPartPa = part.PhysActor; 2079 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1493 if (originalPartPa != null && userExposed)
1494 { 2080 {
1495 PrimitiveBaseShape pbs = newPart.Shape; 2081 PrimitiveBaseShape pbs = newPart.Shape;
1496
1497 newPart.PhysActor 2082 newPart.PhysActor
1498 = m_scene.PhysicsScene.AddPrimShape( 2083 = m_scene.PhysicsScene.AddPrimShape(
1499 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2084 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1500 pbs, 2085 pbs,
1501 newPart.AbsolutePosition, 2086 newPart.AbsolutePosition,
1502 newPart.Scale, 2087 newPart.Scale,
1503 newPart.RotationOffset, 2088 newPart.GetWorldRotation(),
1504 originalPartPa.IsPhysical, 2089 isphys,
2090 isphan,
1505 newPart.LocalId); 2091 newPart.LocalId);
1506 2092
1507 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2093 newPart.DoPhysicsPropertyUpdate(isphys, true);
1508 } 2094 */
2095 if (userExposed)
2096 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2097// }
1509 } 2098 }
1510 2099
1511 if (userExposed) 2100 if (userExposed)
1512 { 2101 {
1513 dupe.UpdateParentIDs(); 2102// done above dupe.UpdateParentIDs();
2103
2104 if (dupe.m_rootPart.PhysActor != null)
2105 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2106
1514 dupe.HasGroupChanged = true; 2107 dupe.HasGroupChanged = true;
1515 dupe.AttachToBackup(); 2108 dupe.AttachToBackup();
1516 2109
1517 ScheduleGroupForFullUpdate(); 2110 ScheduleGroupForFullUpdate();
1518 } 2111 }
1519 2112
2113 m_dupeInProgress = false;
1520 return dupe; 2114 return dupe;
1521 } 2115 }
1522 2116
@@ -1528,11 +2122,24 @@ namespace OpenSim.Region.Framework.Scenes
1528 /// <param name="cGroupID"></param> 2122 /// <param name="cGroupID"></param>
1529 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2123 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1530 { 2124 {
1531 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2125 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
2126 // give newpart a new local ID lettng old part keep same
2127 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2128 newpart.LocalId = m_scene.AllocateLocalId();
2129
2130 SetRootPart(newpart);
2131 if (userExposed)
2132 RootPart.Velocity = Vector3.Zero; // In case source is moving
1532 } 2133 }
1533 2134
1534 public void ScriptSetPhysicsStatus(bool usePhysics) 2135 public void ScriptSetPhysicsStatus(bool usePhysics)
1535 { 2136 {
2137 if (usePhysics)
2138 {
2139 if (RootPart.KeyframeMotion != null)
2140 RootPart.KeyframeMotion.Stop();
2141 RootPart.KeyframeMotion = null;
2142 }
1536 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2143 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1537 } 2144 }
1538 2145
@@ -1586,7 +2193,7 @@ namespace OpenSim.Region.Framework.Scenes
1586 } 2193 }
1587 } 2194 }
1588 2195
1589 public void applyAngularImpulse(Vector3 impulse) 2196 public void ApplyAngularImpulse(Vector3 impulse)
1590 { 2197 {
1591 PhysicsActor pa = RootPart.PhysActor; 2198 PhysicsActor pa = RootPart.PhysActor;
1592 2199
@@ -1600,36 +2207,12 @@ namespace OpenSim.Region.Framework.Scenes
1600 } 2207 }
1601 } 2208 }
1602 2209
1603 public void setAngularImpulse(Vector3 impulse)
1604 {
1605 PhysicsActor pa = RootPart.PhysActor;
1606
1607 if (pa != null)
1608 {
1609 if (!IsAttachment)
1610 {
1611 pa.Torque = impulse;
1612 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1613 }
1614 }
1615 }
1616
1617 public Vector3 GetTorque() 2210 public Vector3 GetTorque()
1618 { 2211 {
1619 PhysicsActor pa = RootPart.PhysActor; 2212 return RootPart.Torque;
1620
1621 if (pa != null)
1622 {
1623 if (!IsAttachment)
1624 {
1625 Vector3 torque = pa.Torque;
1626 return torque;
1627 }
1628 }
1629
1630 return Vector3.Zero;
1631 } 2213 }
1632 2214
2215 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1633 public void moveToTarget(Vector3 target, float tau) 2216 public void moveToTarget(Vector3 target, float tau)
1634 { 2217 {
1635 if (IsAttachment) 2218 if (IsAttachment)
@@ -1661,6 +2244,46 @@ namespace OpenSim.Region.Framework.Scenes
1661 pa.PIDActive = false; 2244 pa.PIDActive = false;
1662 } 2245 }
1663 2246
2247 public void rotLookAt(Quaternion target, float strength, float damping)
2248 {
2249 SceneObjectPart rootpart = m_rootPart;
2250 if (rootpart != null)
2251 {
2252 if (IsAttachment)
2253 {
2254 /*
2255 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2256 if (avatar != null)
2257 {
2258 Rotate the Av?
2259 } */
2260 }
2261 else
2262 {
2263 if (rootpart.PhysActor != null)
2264 { // APID must be implemented in your physics system for this to function.
2265 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2266 rootpart.PhysActor.APIDStrength = strength;
2267 rootpart.PhysActor.APIDDamping = damping;
2268 rootpart.PhysActor.APIDActive = true;
2269 }
2270 }
2271 }
2272 }
2273
2274 public void stopLookAt()
2275 {
2276 SceneObjectPart rootpart = m_rootPart;
2277 if (rootpart != null)
2278 {
2279 if (rootpart.PhysActor != null)
2280 { // APID must be implemented in your physics system for this to function.
2281 rootpart.PhysActor.APIDActive = false;
2282 }
2283 }
2284
2285 }
2286
1664 /// <summary> 2287 /// <summary>
1665 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2288 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1666 /// </summary> 2289 /// </summary>
@@ -1717,7 +2340,12 @@ namespace OpenSim.Region.Framework.Scenes
1717 /// <param name="cGroupID"></param> 2340 /// <param name="cGroupID"></param>
1718 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2341 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1719 { 2342 {
1720 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2343 // give new ID to the new part, letting old keep original
2344 // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2345 SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2346 newPart.LocalId = m_scene.AllocateLocalId();
2347 newPart.SetParent(this);
2348
1721 AddPart(newPart); 2349 AddPart(newPart);
1722 2350
1723 SetPartAsNonRoot(newPart); 2351 SetPartAsNonRoot(newPart);
@@ -1846,11 +2474,11 @@ namespace OpenSim.Region.Framework.Scenes
1846 /// Immediately send a full update for this scene object. 2474 /// Immediately send a full update for this scene object.
1847 /// </summary> 2475 /// </summary>
1848 public void SendGroupFullUpdate() 2476 public void SendGroupFullUpdate()
1849 { 2477 {
1850 if (IsDeleted) 2478 if (IsDeleted)
1851 return; 2479 return;
1852 2480
1853// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2481// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1854 2482
1855 RootPart.SendFullUpdateToAllClients(); 2483 RootPart.SendFullUpdateToAllClients();
1856 2484
@@ -1969,6 +2597,11 @@ namespace OpenSim.Region.Framework.Scenes
1969 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2597 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1970 public void LinkToGroup(SceneObjectGroup objectGroup) 2598 public void LinkToGroup(SceneObjectGroup objectGroup)
1971 { 2599 {
2600 LinkToGroup(objectGroup, false);
2601 }
2602
2603 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2604 {
1972// m_log.DebugFormat( 2605// m_log.DebugFormat(
1973// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2606// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1974// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2607// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
@@ -1979,6 +2612,15 @@ namespace OpenSim.Region.Framework.Scenes
1979 2612
1980 SceneObjectPart linkPart = objectGroup.m_rootPart; 2613 SceneObjectPart linkPart = objectGroup.m_rootPart;
1981 2614
2615 if (m_rootPart.PhysActor != null)
2616 m_rootPart.PhysActor.Building = true;
2617 if (linkPart.PhysActor != null)
2618 linkPart.PhysActor.Building = true;
2619
2620 // physics flags from group to be applied to linked parts
2621 bool grpusephys = UsesPhysics;
2622 bool grptemporary = IsTemporary;
2623
1982 Vector3 oldGroupPosition = linkPart.GroupPosition; 2624 Vector3 oldGroupPosition = linkPart.GroupPosition;
1983 Quaternion oldRootRotation = linkPart.RotationOffset; 2625 Quaternion oldRootRotation = linkPart.RotationOffset;
1984 2626
@@ -2002,13 +2644,34 @@ namespace OpenSim.Region.Framework.Scenes
2002 2644
2003 lock (m_parts.SyncRoot) 2645 lock (m_parts.SyncRoot)
2004 { 2646 {
2005 int linkNum = PrimCount + 1; 2647 int linkNum;
2648 if (insert)
2649 {
2650 linkNum = 2;
2651 foreach (SceneObjectPart part in Parts)
2652 {
2653 if (part.LinkNum > 1)
2654 part.LinkNum++;
2655 }
2656 }
2657 else
2658 {
2659 linkNum = PrimCount + 1;
2660 }
2006 2661
2007 m_parts.Add(linkPart.UUID, linkPart); 2662 m_parts.Add(linkPart.UUID, linkPart);
2008 2663
2009 linkPart.SetParent(this); 2664 linkPart.SetParent(this);
2010 linkPart.CreateSelected = true; 2665 linkPart.CreateSelected = true;
2011 2666
2667 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2668 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2669 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2670 {
2671 linkPart.PhysActor.link(m_rootPart.PhysActor);
2672 this.Scene.PhysicsScene.AddPhysicsActorTaint(linkPart.PhysActor);
2673 }
2674
2012 linkPart.LinkNum = linkNum++; 2675 linkPart.LinkNum = linkNum++;
2013 2676
2014 SceneObjectPart[] ogParts = objectGroup.Parts; 2677 SceneObjectPart[] ogParts = objectGroup.Parts;
@@ -2021,7 +2684,16 @@ namespace OpenSim.Region.Framework.Scenes
2021 { 2684 {
2022 SceneObjectPart part = ogParts[i]; 2685 SceneObjectPart part = ogParts[i];
2023 if (part.UUID != objectGroup.m_rootPart.UUID) 2686 if (part.UUID != objectGroup.m_rootPart.UUID)
2687 {
2024 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2688 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2689 // let physics know
2690 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2691 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2692 {
2693 part.PhysActor.link(m_rootPart.PhysActor);
2694 this.Scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2695 }
2696 }
2025 part.ClearUndoState(); 2697 part.ClearUndoState();
2026 } 2698 }
2027 } 2699 }
@@ -2030,7 +2702,7 @@ namespace OpenSim.Region.Framework.Scenes
2030 objectGroup.IsDeleted = true; 2702 objectGroup.IsDeleted = true;
2031 2703
2032 objectGroup.m_parts.Clear(); 2704 objectGroup.m_parts.Clear();
2033 2705
2034 // Can't do this yet since backup still makes use of the root part without any synchronization 2706 // Can't do this yet since backup still makes use of the root part without any synchronization
2035// objectGroup.m_rootPart = null; 2707// objectGroup.m_rootPart = null;
2036 2708
@@ -2041,6 +2713,9 @@ namespace OpenSim.Region.Framework.Scenes
2041 // unmoved prims! 2713 // unmoved prims!
2042 ResetChildPrimPhysicsPositions(); 2714 ResetChildPrimPhysicsPositions();
2043 2715
2716 if (m_rootPart.PhysActor != null)
2717 m_rootPart.PhysActor.Building = false;
2718
2044 //HasGroupChanged = true; 2719 //HasGroupChanged = true;
2045 //ScheduleGroupForFullUpdate(); 2720 //ScheduleGroupForFullUpdate();
2046 } 2721 }
@@ -2108,7 +2783,10 @@ namespace OpenSim.Region.Framework.Scenes
2108// m_log.DebugFormat( 2783// m_log.DebugFormat(
2109// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 2784// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2110// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 2785// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2111 2786
2787 if (m_rootPart.PhysActor != null)
2788 m_rootPart.PhysActor.Building = true;
2789
2112 linkPart.ClearUndoState(); 2790 linkPart.ClearUndoState();
2113 2791
2114 Quaternion worldRot = linkPart.GetWorldRotation(); 2792 Quaternion worldRot = linkPart.GetWorldRotation();
@@ -2168,6 +2846,14 @@ namespace OpenSim.Region.Framework.Scenes
2168 2846
2169 // When we delete a group, we currently have to force persist to the database if the object id has changed 2847 // When we delete a group, we currently have to force persist to the database if the object id has changed
2170 // (since delete works by deleting all rows which have a given object id) 2848 // (since delete works by deleting all rows which have a given object id)
2849
2850 // this is as it seems to be in sl now
2851 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2852 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2853
2854 if (m_rootPart.PhysActor != null)
2855 m_rootPart.PhysActor.Building = false;
2856
2171 objectGroup.HasGroupChangedDueToDelink = true; 2857 objectGroup.HasGroupChangedDueToDelink = true;
2172 2858
2173 return objectGroup; 2859 return objectGroup;
@@ -2179,6 +2865,7 @@ namespace OpenSim.Region.Framework.Scenes
2179 /// <param name="objectGroup"></param> 2865 /// <param name="objectGroup"></param>
2180 public virtual void DetachFromBackup() 2866 public virtual void DetachFromBackup()
2181 { 2867 {
2868 m_scene.SceneGraph.FireDetachFromBackup(this);
2182 if (m_isBackedUp && Scene != null) 2869 if (m_isBackedUp && Scene != null)
2183 m_scene.EventManager.OnBackup -= ProcessBackup; 2870 m_scene.EventManager.OnBackup -= ProcessBackup;
2184 2871
@@ -2197,7 +2884,8 @@ namespace OpenSim.Region.Framework.Scenes
2197 2884
2198 axPos *= parentRot; 2885 axPos *= parentRot;
2199 part.OffsetPosition = axPos; 2886 part.OffsetPosition = axPos;
2200 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2887 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2888 part.GroupPosition = newPos;
2201 part.OffsetPosition = Vector3.Zero; 2889 part.OffsetPosition = Vector3.Zero;
2202 part.RotationOffset = worldRot; 2890 part.RotationOffset = worldRot;
2203 2891
@@ -2208,7 +2896,7 @@ namespace OpenSim.Region.Framework.Scenes
2208 2896
2209 part.LinkNum = linkNum; 2897 part.LinkNum = linkNum;
2210 2898
2211 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2899 part.OffsetPosition = newPos - AbsolutePosition;
2212 2900
2213 Quaternion rootRotation = m_rootPart.RotationOffset; 2901 Quaternion rootRotation = m_rootPart.RotationOffset;
2214 2902
@@ -2218,7 +2906,7 @@ namespace OpenSim.Region.Framework.Scenes
2218 2906
2219 parentRot = m_rootPart.RotationOffset; 2907 parentRot = m_rootPart.RotationOffset;
2220 oldRot = part.RotationOffset; 2908 oldRot = part.RotationOffset;
2221 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2909 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2222 part.RotationOffset = newRot; 2910 part.RotationOffset = newRot;
2223 } 2911 }
2224 2912
@@ -2470,8 +3158,31 @@ namespace OpenSim.Region.Framework.Scenes
2470 } 3158 }
2471 } 3159 }
2472 3160
3161/*
3162 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2473 for (int i = 0; i < parts.Length; i++) 3163 for (int i = 0; i < parts.Length; i++)
2474 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3164 {
3165 if (parts[i] != RootPart)
3166 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
3167 }
3168*/
3169 if (parts.Length > 1)
3170 {
3171 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3172
3173 for (int i = 0; i < parts.Length; i++)
3174 {
3175
3176 if (parts[i].UUID != m_rootPart.UUID)
3177 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3178 }
3179
3180 if (m_rootPart.PhysActor != null)
3181 m_rootPart.PhysActor.Building = false;
3182 }
3183 else
3184 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
3185
2475 } 3186 }
2476 } 3187 }
2477 3188
@@ -2484,6 +3195,17 @@ namespace OpenSim.Region.Framework.Scenes
2484 } 3195 }
2485 } 3196 }
2486 3197
3198
3199
3200 /// <summary>
3201 /// Gets the number of parts
3202 /// </summary>
3203 /// <returns></returns>
3204 public int GetPartCount()
3205 {
3206 return Parts.Count();
3207 }
3208
2487 /// <summary> 3209 /// <summary>
2488 /// Update the texture entry for this part 3210 /// Update the texture entry for this part
2489 /// </summary> 3211 /// </summary>
@@ -2545,11 +3267,6 @@ namespace OpenSim.Region.Framework.Scenes
2545 /// <param name="scale"></param> 3267 /// <param name="scale"></param>
2546 public void GroupResize(Vector3 scale) 3268 public void GroupResize(Vector3 scale)
2547 { 3269 {
2548// m_log.DebugFormat(
2549// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2550
2551 RootPart.StoreUndoState(true);
2552
2553 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3270 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2554 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3271 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
2555 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); 3272 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
@@ -2576,7 +3293,6 @@ namespace OpenSim.Region.Framework.Scenes
2576 SceneObjectPart obPart = parts[i]; 3293 SceneObjectPart obPart = parts[i];
2577 if (obPart.UUID != m_rootPart.UUID) 3294 if (obPart.UUID != m_rootPart.UUID)
2578 { 3295 {
2579// obPart.IgnoreUndoUpdate = true;
2580 Vector3 oldSize = new Vector3(obPart.Scale); 3296 Vector3 oldSize = new Vector3(obPart.Scale);
2581 3297
2582 float f = 1.0f; 3298 float f = 1.0f;
@@ -2640,8 +3356,6 @@ namespace OpenSim.Region.Framework.Scenes
2640 z *= a; 3356 z *= a;
2641 } 3357 }
2642 } 3358 }
2643
2644// obPart.IgnoreUndoUpdate = false;
2645 } 3359 }
2646 } 3360 }
2647 } 3361 }
@@ -2651,9 +3365,7 @@ namespace OpenSim.Region.Framework.Scenes
2651 prevScale.Y *= y; 3365 prevScale.Y *= y;
2652 prevScale.Z *= z; 3366 prevScale.Z *= z;
2653 3367
2654// RootPart.IgnoreUndoUpdate = true;
2655 RootPart.Resize(prevScale); 3368 RootPart.Resize(prevScale);
2656// RootPart.IgnoreUndoUpdate = false;
2657 3369
2658 parts = m_parts.GetArray(); 3370 parts = m_parts.GetArray();
2659 for (int i = 0; i < parts.Length; i++) 3371 for (int i = 0; i < parts.Length; i++)
@@ -2662,8 +3374,6 @@ namespace OpenSim.Region.Framework.Scenes
2662 3374
2663 if (obPart.UUID != m_rootPart.UUID) 3375 if (obPart.UUID != m_rootPart.UUID)
2664 { 3376 {
2665 obPart.IgnoreUndoUpdate = true;
2666
2667 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3377 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2668 currentpos.X *= x; 3378 currentpos.X *= x;
2669 currentpos.Y *= y; 3379 currentpos.Y *= y;
@@ -2676,16 +3386,12 @@ namespace OpenSim.Region.Framework.Scenes
2676 3386
2677 obPart.Resize(newSize); 3387 obPart.Resize(newSize);
2678 obPart.UpdateOffSet(currentpos); 3388 obPart.UpdateOffSet(currentpos);
2679
2680 obPart.IgnoreUndoUpdate = false;
2681 } 3389 }
2682 3390
2683// obPart.IgnoreUndoUpdate = false; 3391 HasGroupChanged = true;
2684// obPart.StoreUndoState(); 3392 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3393 ScheduleGroupForTerseUpdate();
2685 } 3394 }
2686
2687// m_log.DebugFormat(
2688// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
2689 } 3395 }
2690 3396
2691 #endregion 3397 #endregion
@@ -2698,14 +3404,6 @@ namespace OpenSim.Region.Framework.Scenes
2698 /// <param name="pos"></param> 3404 /// <param name="pos"></param>
2699 public void UpdateGroupPosition(Vector3 pos) 3405 public void UpdateGroupPosition(Vector3 pos)
2700 { 3406 {
2701// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2702
2703 RootPart.StoreUndoState(true);
2704
2705// SceneObjectPart[] parts = m_parts.GetArray();
2706// for (int i = 0; i < parts.Length; i++)
2707// parts[i].StoreUndoState();
2708
2709 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3407 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2710 { 3408 {
2711 if (IsAttachment) 3409 if (IsAttachment)
@@ -2738,21 +3436,17 @@ namespace OpenSim.Region.Framework.Scenes
2738 /// </summary> 3436 /// </summary>
2739 /// <param name="pos"></param> 3437 /// <param name="pos"></param>
2740 /// <param name="localID"></param> 3438 /// <param name="localID"></param>
3439 ///
3440
2741 public void UpdateSinglePosition(Vector3 pos, uint localID) 3441 public void UpdateSinglePosition(Vector3 pos, uint localID)
2742 { 3442 {
2743 SceneObjectPart part = GetPart(localID); 3443 SceneObjectPart part = GetPart(localID);
2744 3444
2745// SceneObjectPart[] parts = m_parts.GetArray();
2746// for (int i = 0; i < parts.Length; i++)
2747// parts[i].StoreUndoState();
2748
2749 if (part != null) 3445 if (part != null)
2750 { 3446 {
2751// m_log.DebugFormat( 3447// unlock parts position change
2752// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3448 if (m_rootPart.PhysActor != null)
2753 3449 m_rootPart.PhysActor.Building = true;
2754 part.StoreUndoState(false);
2755 part.IgnoreUndoUpdate = true;
2756 3450
2757 if (part.UUID == m_rootPart.UUID) 3451 if (part.UUID == m_rootPart.UUID)
2758 { 3452 {
@@ -2763,8 +3457,10 @@ namespace OpenSim.Region.Framework.Scenes
2763 part.UpdateOffSet(pos); 3457 part.UpdateOffSet(pos);
2764 } 3458 }
2765 3459
3460 if (m_rootPart.PhysActor != null)
3461 m_rootPart.PhysActor.Building = false;
3462
2766 HasGroupChanged = true; 3463 HasGroupChanged = true;
2767 part.IgnoreUndoUpdate = false;
2768 } 3464 }
2769 } 3465 }
2770 3466
@@ -2774,13 +3470,7 @@ namespace OpenSim.Region.Framework.Scenes
2774 /// <param name="pos"></param> 3470 /// <param name="pos"></param>
2775 public void UpdateRootPosition(Vector3 pos) 3471 public void UpdateRootPosition(Vector3 pos)
2776 { 3472 {
2777// m_log.DebugFormat( 3473 // needs to be called with phys building true
2778// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
2779
2780// SceneObjectPart[] parts = m_parts.GetArray();
2781// for (int i = 0; i < parts.Length; i++)
2782// parts[i].StoreUndoState();
2783
2784 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3474 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2785 Vector3 oldPos = 3475 Vector3 oldPos =
2786 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3476 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
@@ -2803,7 +3493,14 @@ namespace OpenSim.Region.Framework.Scenes
2803 AbsolutePosition = newPos; 3493 AbsolutePosition = newPos;
2804 3494
2805 HasGroupChanged = true; 3495 HasGroupChanged = true;
2806 ScheduleGroupForTerseUpdate(); 3496 if (m_rootPart.Undoing)
3497 {
3498 ScheduleGroupForFullUpdate();
3499 }
3500 else
3501 {
3502 ScheduleGroupForTerseUpdate();
3503 }
2807 } 3504 }
2808 3505
2809 #endregion 3506 #endregion
@@ -2816,17 +3513,6 @@ namespace OpenSim.Region.Framework.Scenes
2816 /// <param name="rot"></param> 3513 /// <param name="rot"></param>
2817 public void UpdateGroupRotationR(Quaternion rot) 3514 public void UpdateGroupRotationR(Quaternion rot)
2818 { 3515 {
2819// m_log.DebugFormat(
2820// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
2821
2822// SceneObjectPart[] parts = m_parts.GetArray();
2823// for (int i = 0; i < parts.Length; i++)
2824// parts[i].StoreUndoState();
2825
2826 m_rootPart.StoreUndoState(true);
2827
2828 m_rootPart.UpdateRotation(rot);
2829
2830 PhysicsActor actor = m_rootPart.PhysActor; 3516 PhysicsActor actor = m_rootPart.PhysActor;
2831 if (actor != null) 3517 if (actor != null)
2832 { 3518 {
@@ -2845,16 +3531,6 @@ namespace OpenSim.Region.Framework.Scenes
2845 /// <param name="rot"></param> 3531 /// <param name="rot"></param>
2846 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3532 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
2847 { 3533 {
2848// m_log.DebugFormat(
2849// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
2850
2851// SceneObjectPart[] parts = m_parts.GetArray();
2852// for (int i = 0; i < parts.Length; i++)
2853// parts[i].StoreUndoState();
2854
2855 RootPart.StoreUndoState(true);
2856 RootPart.IgnoreUndoUpdate = true;
2857
2858 m_rootPart.UpdateRotation(rot); 3534 m_rootPart.UpdateRotation(rot);
2859 3535
2860 PhysicsActor actor = m_rootPart.PhysActor; 3536 PhysicsActor actor = m_rootPart.PhysActor;
@@ -2868,8 +3544,6 @@ namespace OpenSim.Region.Framework.Scenes
2868 3544
2869 HasGroupChanged = true; 3545 HasGroupChanged = true;
2870 ScheduleGroupForTerseUpdate(); 3546 ScheduleGroupForTerseUpdate();
2871
2872 RootPart.IgnoreUndoUpdate = false;
2873 } 3547 }
2874 3548
2875 /// <summary> 3549 /// <summary>
@@ -2882,13 +3556,11 @@ namespace OpenSim.Region.Framework.Scenes
2882 SceneObjectPart part = GetPart(localID); 3556 SceneObjectPart part = GetPart(localID);
2883 3557
2884 SceneObjectPart[] parts = m_parts.GetArray(); 3558 SceneObjectPart[] parts = m_parts.GetArray();
2885 for (int i = 0; i < parts.Length; i++)
2886 parts[i].StoreUndoState();
2887 3559
2888 if (part != null) 3560 if (part != null)
2889 { 3561 {
2890// m_log.DebugFormat( 3562 if (m_rootPart.PhysActor != null)
2891// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 3563 m_rootPart.PhysActor.Building = true;
2892 3564
2893 if (part.UUID == m_rootPart.UUID) 3565 if (part.UUID == m_rootPart.UUID)
2894 { 3566 {
@@ -2898,6 +3570,9 @@ namespace OpenSim.Region.Framework.Scenes
2898 { 3570 {
2899 part.UpdateRotation(rot); 3571 part.UpdateRotation(rot);
2900 } 3572 }
3573
3574 if (m_rootPart.PhysActor != null)
3575 m_rootPart.PhysActor.Building = false;
2901 } 3576 }
2902 } 3577 }
2903 3578
@@ -2911,12 +3586,8 @@ namespace OpenSim.Region.Framework.Scenes
2911 SceneObjectPart part = GetPart(localID); 3586 SceneObjectPart part = GetPart(localID);
2912 if (part != null) 3587 if (part != null)
2913 { 3588 {
2914// m_log.DebugFormat( 3589 if (m_rootPart.PhysActor != null)
2915// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 3590 m_rootPart.PhysActor.Building = true;
2916// part.Name, part.LocalId, rot);
2917
2918 part.StoreUndoState();
2919 part.IgnoreUndoUpdate = true;
2920 3591
2921 if (part.UUID == m_rootPart.UUID) 3592 if (part.UUID == m_rootPart.UUID)
2922 { 3593 {
@@ -2929,7 +3600,8 @@ namespace OpenSim.Region.Framework.Scenes
2929 part.OffsetPosition = pos; 3600 part.OffsetPosition = pos;
2930 } 3601 }
2931 3602
2932 part.IgnoreUndoUpdate = false; 3603 if (m_rootPart.PhysActor != null)
3604 m_rootPart.PhysActor.Building = false;
2933 } 3605 }
2934 } 3606 }
2935 3607
@@ -2939,15 +3611,12 @@ namespace OpenSim.Region.Framework.Scenes
2939 /// <param name="rot"></param> 3611 /// <param name="rot"></param>
2940 public void UpdateRootRotation(Quaternion rot) 3612 public void UpdateRootRotation(Quaternion rot)
2941 { 3613 {
2942// m_log.DebugFormat( 3614 // needs to be called with phys building true
2943// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
2944// Name, LocalId, rot);
2945
2946 Quaternion axRot = rot; 3615 Quaternion axRot = rot;
2947 Quaternion oldParentRot = m_rootPart.RotationOffset; 3616 Quaternion oldParentRot = m_rootPart.RotationOffset;
2948 3617
2949 m_rootPart.StoreUndoState(); 3618 //Don't use UpdateRotation because it schedules an update prematurely
2950 m_rootPart.UpdateRotation(rot); 3619 m_rootPart.RotationOffset = rot;
2951 3620
2952 PhysicsActor pa = m_rootPart.PhysActor; 3621 PhysicsActor pa = m_rootPart.PhysActor;
2953 3622
@@ -2963,35 +3632,135 @@ namespace OpenSim.Region.Framework.Scenes
2963 SceneObjectPart prim = parts[i]; 3632 SceneObjectPart prim = parts[i];
2964 if (prim.UUID != m_rootPart.UUID) 3633 if (prim.UUID != m_rootPart.UUID)
2965 { 3634 {
2966 prim.IgnoreUndoUpdate = true; 3635 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3636 NewRot = Quaternion.Inverse(axRot) * NewRot;
3637 prim.RotationOffset = NewRot;
3638
2967 Vector3 axPos = prim.OffsetPosition; 3639 Vector3 axPos = prim.OffsetPosition;
3640
2968 axPos *= oldParentRot; 3641 axPos *= oldParentRot;
2969 axPos *= Quaternion.Inverse(axRot); 3642 axPos *= Quaternion.Inverse(axRot);
2970 prim.OffsetPosition = axPos; 3643 prim.OffsetPosition = axPos;
2971 Quaternion primsRot = prim.RotationOffset; 3644 }
2972 Quaternion newRot = oldParentRot * primsRot; 3645 }
2973 newRot = Quaternion.Inverse(axRot) * newRot;
2974 prim.RotationOffset = newRot;
2975 prim.ScheduleTerseUpdate();
2976 prim.IgnoreUndoUpdate = false;
2977 }
2978 }
2979
2980// for (int i = 0; i < parts.Length; i++)
2981// {
2982// SceneObjectPart childpart = parts[i];
2983// if (childpart != m_rootPart)
2984// {
2985//// childpart.IgnoreUndoUpdate = false;
2986//// childpart.StoreUndoState();
2987// }
2988// }
2989 3646
2990 m_rootPart.ScheduleTerseUpdate(); 3647 HasGroupChanged = true;
3648 ScheduleGroupForFullUpdate();
3649 }
2991 3650
2992// m_log.DebugFormat( 3651 private enum updatetype :int
2993// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3652 {
2994// Name, LocalId, rot); 3653 none = 0,
3654 partterse = 1,
3655 partfull = 2,
3656 groupterse = 3,
3657 groupfull = 4
3658 }
3659
3660 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3661 {
3662 // TODO this still as excessive *.Schedule*Update()s
3663
3664 if (part != null && part.ParentGroup != null)
3665 {
3666 ObjectChangeType change = data.change;
3667 bool togroup = ((change & ObjectChangeType.Group) != 0);
3668 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
3669
3670 SceneObjectGroup group = part.ParentGroup;
3671 PhysicsActor pha = group.RootPart.PhysActor;
3672
3673 updatetype updateType = updatetype.none;
3674
3675 if (togroup)
3676 {
3677 // related to group
3678 if ((change & ObjectChangeType.Position) != 0)
3679 {
3680 group.AbsolutePosition = data.position;
3681 updateType = updatetype.groupterse;
3682 }
3683 if ((change & ObjectChangeType.Rotation) != 0)
3684 {
3685 group.RootPart.UpdateRotation(data.rotation);
3686 updateType = updatetype.none;
3687 }
3688 if ((change & ObjectChangeType.Scale) != 0)
3689 {
3690 if (pha != null)
3691 pha.Building = true;
3692
3693 group.GroupResize(data.scale);
3694 updateType = updatetype.none;
3695
3696 if (pha != null)
3697 pha.Building = false;
3698 }
3699 }
3700 else
3701 {
3702 // related to single prim in a link-set ( ie group)
3703 if (pha != null)
3704 pha.Building = true;
3705
3706 // root part is special
3707 // parts offset positions or rotations need to change also
3708
3709 if (part == group.RootPart)
3710 {
3711 if ((change & ObjectChangeType.Position) != 0)
3712 group.UpdateRootPosition(data.position);
3713 if ((change & ObjectChangeType.Rotation) != 0)
3714 group.UpdateRootRotation(data.rotation);
3715 if ((change & ObjectChangeType.Scale) != 0)
3716 part.Resize(data.scale);
3717 }
3718 else
3719 {
3720 if ((change & ObjectChangeType.Position) != 0)
3721 {
3722 part.OffsetPosition = data.position;
3723 updateType = updatetype.partterse;
3724 }
3725 if ((change & ObjectChangeType.Rotation) != 0)
3726 {
3727 part.UpdateRotation(data.rotation);
3728 updateType = updatetype.none;
3729 }
3730 if ((change & ObjectChangeType.Scale) != 0)
3731 {
3732 part.Resize(data.scale);
3733 updateType = updatetype.none;
3734 }
3735 }
3736
3737 if (pha != null)
3738 pha.Building = false;
3739 }
3740
3741 if (updateType != updatetype.none)
3742 {
3743 group.HasGroupChanged = true;
3744
3745 switch (updateType)
3746 {
3747 case updatetype.partterse:
3748 part.ScheduleTerseUpdate();
3749 break;
3750 case updatetype.partfull:
3751 part.ScheduleFullUpdate();
3752 break;
3753 case updatetype.groupterse:
3754 group.ScheduleGroupForTerseUpdate();
3755 break;
3756 case updatetype.groupfull:
3757 group.ScheduleGroupForFullUpdate();
3758 break;
3759 default:
3760 break;
3761 }
3762 }
3763 }
2995 } 3764 }
2996 3765
2997 #endregion 3766 #endregion
@@ -3211,11 +3980,38 @@ namespace OpenSim.Region.Framework.Scenes
3211 } 3980 }
3212 } 3981 }
3213 } 3982 }
3214 3983
3984 public Vector3 GetGeometricCenter()
3985 {
3986 // this is not real geometric center but a average of positions relative to root prim acording to
3987 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
3988 // ignoring tortured prims details since sl also seems to ignore
3989 // so no real use in doing it on physics
3990
3991 Vector3 gc = Vector3.Zero;
3992
3993 int nparts = m_parts.Count;
3994 if (nparts <= 1)
3995 return gc;
3996
3997 SceneObjectPart[] parts = m_parts.GetArray();
3998 nparts = parts.Length; // just in case it changed
3999 if (nparts <= 1)
4000 return gc;
4001
4002 // average all parts positions
4003 for (int i = 0; i < nparts; i++)
4004 gc += parts[i].GetWorldPosition();
4005 gc /= nparts;
4006
4007 // relative to root:
4008 gc -= AbsolutePosition;
4009 return gc;
4010 }
4011
3215 public float GetMass() 4012 public float GetMass()
3216 { 4013 {
3217 float retmass = 0f; 4014 float retmass = 0f;
3218
3219 SceneObjectPart[] parts = m_parts.GetArray(); 4015 SceneObjectPart[] parts = m_parts.GetArray();
3220 for (int i = 0; i < parts.Length; i++) 4016 for (int i = 0; i < parts.Length; i++)
3221 retmass += parts[i].GetMass(); 4017 retmass += parts[i].GetMass();
@@ -3376,6 +4172,14 @@ namespace OpenSim.Region.Framework.Scenes
3376 FromItemID = uuid; 4172 FromItemID = uuid;
3377 } 4173 }
3378 4174
4175 public void ResetOwnerChangeFlag()
4176 {
4177 ForEachPart(delegate(SceneObjectPart part)
4178 {
4179 part.ResetOwnerChangeFlag();
4180 });
4181 }
4182
3379 #endregion 4183 #endregion
3380 } 4184 }
3381} 4185}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 046553b..c73fc98 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -121,6 +122,11 @@ namespace OpenSim.Region.Framework.Scenes
121 /// Denote all sides of the prim 122 /// Denote all sides of the prim
122 /// </value> 123 /// </value>
123 public const int ALL_SIDES = -1; 124 public const int ALL_SIDES = -1;
125
126 private const scriptEvents PhyscicsNeededSubsEvents = (
127 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
128 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
129 );
124 130
125 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 131 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
126 132
@@ -182,6 +188,15 @@ namespace OpenSim.Region.Framework.Scenes
182 188
183 public uint TimeStampTerse; 189 public uint TimeStampTerse;
184 190
191 // The following two are to hold the attachment data
192 // while an object is inworld
193 [XmlIgnore]
194 public byte AttachPoint = 0;
195
196 [XmlIgnore]
197 public Vector3 AttachOffset = Vector3.Zero;
198
199 [XmlIgnore]
185 public int STATUS_ROTATE_X; 200 public int STATUS_ROTATE_X;
186 201
187 public int STATUS_ROTATE_Y; 202 public int STATUS_ROTATE_Y;
@@ -208,8 +223,7 @@ namespace OpenSim.Region.Framework.Scenes
208 223
209 public Vector3 RotationAxis = Vector3.One; 224 public Vector3 RotationAxis = Vector3.One;
210 225
211 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 226 public bool VolumeDetectActive;
212 // Certainly this must be a persistant setting finally
213 227
214 public bool IsWaitingForFirstSpinUpdatePacket; 228 public bool IsWaitingForFirstSpinUpdatePacket;
215 229
@@ -249,10 +263,10 @@ namespace OpenSim.Region.Framework.Scenes
249 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 263 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
250 private Vector3 m_sitTargetPosition; 264 private Vector3 m_sitTargetPosition;
251 private string m_sitAnimation = "SIT"; 265 private string m_sitAnimation = "SIT";
266 private bool m_occupied; // KF if any av is sitting on this prim
252 private string m_text = String.Empty; 267 private string m_text = String.Empty;
253 private string m_touchName = String.Empty; 268 private string m_touchName = String.Empty;
254 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 269 private UndoRedoState m_UndoRedo = null;
255 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5);
256 270
257 private bool m_passTouches; 271 private bool m_passTouches;
258 272
@@ -280,7 +294,16 @@ namespace OpenSim.Region.Framework.Scenes
280 protected Vector3 m_lastAcceleration; 294 protected Vector3 m_lastAcceleration;
281 protected Vector3 m_lastAngularVelocity; 295 protected Vector3 m_lastAngularVelocity;
282 protected int m_lastTerseSent; 296 protected int m_lastTerseSent;
283 297 protected float m_buoyancy = 0.0f;
298 protected Vector3 m_force;
299 protected Vector3 m_torque;
300
301 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
302 protected float m_density = 1000.0f; // in kg/m^3
303 protected float m_gravitymod = 1.0f;
304 protected float m_friction = 0.6f; // wood
305 protected float m_bounce = 0.5f; // wood
306
284 /// <summary> 307 /// <summary>
285 /// Stores media texture data 308 /// Stores media texture data
286 /// </summary> 309 /// </summary>
@@ -296,6 +319,17 @@ namespace OpenSim.Region.Framework.Scenes
296 private UUID m_collisionSound; 319 private UUID m_collisionSound;
297 private float m_collisionSoundVolume; 320 private float m_collisionSoundVolume;
298 321
322
323 private SOPVehicle m_vehicle = null;
324
325 private KeyframeMotion m_keyframeMotion = null;
326
327 public KeyframeMotion KeyframeMotion
328 {
329 get; set;
330 }
331
332
299 #endregion Fields 333 #endregion Fields
300 334
301// ~SceneObjectPart() 335// ~SceneObjectPart()
@@ -338,7 +372,7 @@ namespace OpenSim.Region.Framework.Scenes
338 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 372 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
339 Quaternion rotationOffset, Vector3 offsetPosition) : this() 373 Quaternion rotationOffset, Vector3 offsetPosition) : this()
340 { 374 {
341 m_name = "Primitive"; 375 m_name = "Object";
342 376
343 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 377 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
344 LastOwnerID = CreatorID = OwnerID = ownerID; 378 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -378,7 +412,7 @@ namespace OpenSim.Region.Framework.Scenes
378 private uint _ownerMask = (uint)PermissionMask.All; 412 private uint _ownerMask = (uint)PermissionMask.All;
379 private uint _groupMask = (uint)PermissionMask.None; 413 private uint _groupMask = (uint)PermissionMask.None;
380 private uint _everyoneMask = (uint)PermissionMask.None; 414 private uint _everyoneMask = (uint)PermissionMask.None;
381 private uint _nextOwnerMask = (uint)PermissionMask.All; 415 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
382 private PrimFlags _flags = PrimFlags.None; 416 private PrimFlags _flags = PrimFlags.None;
383 private DateTime m_expires; 417 private DateTime m_expires;
384 private DateTime m_rezzed; 418 private DateTime m_rezzed;
@@ -472,12 +506,16 @@ namespace OpenSim.Region.Framework.Scenes
472 } 506 }
473 507
474 /// <value> 508 /// <value>
475 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 509 /// Get the inventory list
476 /// </value> 510 /// </value>
477 public TaskInventoryDictionary TaskInventory 511 public TaskInventoryDictionary TaskInventory
478 { 512 {
479 get { return m_inventory.Items; } 513 get {
480 set { m_inventory.Items = value; } 514 return m_inventory.Items;
515 }
516 set {
517 m_inventory.Items = value;
518 }
481 } 519 }
482 520
483 /// <summary> 521 /// <summary>
@@ -527,20 +565,6 @@ namespace OpenSim.Region.Framework.Scenes
527 } 565 }
528 } 566 }
529 567
530 public byte Material
531 {
532 get { return (byte) m_material; }
533 set
534 {
535 m_material = (Material)value;
536
537 PhysicsActor pa = PhysActor;
538
539 if (pa != null)
540 pa.SetMaterial((int)value);
541 }
542 }
543
544 public bool PassTouches 568 public bool PassTouches
545 { 569 {
546 get { return m_passTouches; } 570 get { return m_passTouches; }
@@ -623,14 +647,12 @@ namespace OpenSim.Region.Framework.Scenes
623 set { m_LoopSoundSlavePrims = value; } 647 set { m_LoopSoundSlavePrims = value; }
624 } 648 }
625 649
626
627 public Byte[] TextureAnimation 650 public Byte[] TextureAnimation
628 { 651 {
629 get { return m_TextureAnimation; } 652 get { return m_TextureAnimation; }
630 set { m_TextureAnimation = value; } 653 set { m_TextureAnimation = value; }
631 } 654 }
632 655
633
634 public Byte[] ParticleSystem 656 public Byte[] ParticleSystem
635 { 657 {
636 get { return m_particleSystem; } 658 get { return m_particleSystem; }
@@ -667,8 +689,12 @@ namespace OpenSim.Region.Framework.Scenes
667 { 689 {
668 // If this is a linkset, we don't want the physics engine mucking up our group position here. 690 // If this is a linkset, we don't want the physics engine mucking up our group position here.
669 PhysicsActor actor = PhysActor; 691 PhysicsActor actor = PhysActor;
670 if (actor != null && ParentID == 0) 692 if (ParentID == 0)
671 m_groupPosition = actor.Position; 693 {
694 if (actor != null)
695 m_groupPosition = actor.Position;
696 return m_groupPosition;
697 }
672 698
673 if (ParentGroup.IsAttachment) 699 if (ParentGroup.IsAttachment)
674 { 700 {
@@ -677,12 +703,14 @@ namespace OpenSim.Region.Framework.Scenes
677 return sp.AbsolutePosition; 703 return sp.AbsolutePosition;
678 } 704 }
679 705
706 // use root prim's group position. Physics may have updated it
707 if (ParentGroup.RootPart != this)
708 m_groupPosition = ParentGroup.RootPart.GroupPosition;
680 return m_groupPosition; 709 return m_groupPosition;
681 } 710 }
682 set 711 set
683 { 712 {
684 m_groupPosition = value; 713 m_groupPosition = value;
685
686 PhysicsActor actor = PhysActor; 714 PhysicsActor actor = PhysActor;
687 if (actor != null) 715 if (actor != null)
688 { 716 {
@@ -708,16 +736,6 @@ namespace OpenSim.Region.Framework.Scenes
708 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 736 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
709 } 737 }
710 } 738 }
711
712 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
713 if (SitTargetAvatar != UUID.Zero)
714 {
715 ScenePresence avatar;
716 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
717 {
718 avatar.ParentPosition = GetWorldPosition();
719 }
720 }
721 } 739 }
722 } 740 }
723 741
@@ -726,7 +744,7 @@ namespace OpenSim.Region.Framework.Scenes
726 get { return m_offsetPosition; } 744 get { return m_offsetPosition; }
727 set 745 set
728 { 746 {
729// StoreUndoState(); 747 Vector3 oldpos = m_offsetPosition;
730 m_offsetPosition = value; 748 m_offsetPosition = value;
731 749
732 if (ParentGroup != null && !ParentGroup.IsDeleted) 750 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -741,7 +759,22 @@ namespace OpenSim.Region.Framework.Scenes
741 if (ParentGroup.Scene != null) 759 if (ParentGroup.Scene != null)
742 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 760 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
743 } 761 }
762
763 if (!m_parentGroup.m_dupeInProgress)
764 {
765 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
766 foreach (ScenePresence av in avs)
767 {
768 if (av.ParentID == m_localId)
769 {
770 Vector3 offset = (m_offsetPosition - oldpos);
771 av.AbsolutePosition += offset;
772 av.SendAvatarDataToAllAgents();
773 }
774 }
775 }
744 } 776 }
777 TriggerScriptChangedEvent(Changed.POSITION);
745 } 778 }
746 } 779 }
747 780
@@ -790,7 +823,7 @@ namespace OpenSim.Region.Framework.Scenes
790 823
791 set 824 set
792 { 825 {
793 StoreUndoState(); 826// StoreUndoState();
794 m_rotationOffset = value; 827 m_rotationOffset = value;
795 828
796 PhysicsActor actor = PhysActor; 829 PhysicsActor actor = PhysActor;
@@ -878,7 +911,7 @@ namespace OpenSim.Region.Framework.Scenes
878 get 911 get
879 { 912 {
880 PhysicsActor actor = PhysActor; 913 PhysicsActor actor = PhysActor;
881 if ((actor != null) && actor.IsPhysical) 914 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
882 { 915 {
883 m_angularVelocity = actor.RotationalVelocity; 916 m_angularVelocity = actor.RotationalVelocity;
884 } 917 }
@@ -890,7 +923,16 @@ namespace OpenSim.Region.Framework.Scenes
890 /// <summary></summary> 923 /// <summary></summary>
891 public Vector3 Acceleration 924 public Vector3 Acceleration
892 { 925 {
893 get { return m_acceleration; } 926 get
927 {
928 PhysicsActor actor = PhysActor;
929 if (actor != null)
930 {
931 m_acceleration = actor.Acceleration;
932 }
933 return m_acceleration;
934 }
935
894 set { m_acceleration = value; } 936 set { m_acceleration = value; }
895 } 937 }
896 938
@@ -947,7 +989,10 @@ namespace OpenSim.Region.Framework.Scenes
947 public PrimitiveBaseShape Shape 989 public PrimitiveBaseShape Shape
948 { 990 {
949 get { return m_shape; } 991 get { return m_shape; }
950 set { m_shape = value;} 992 set
993 {
994 m_shape = value;
995 }
951 } 996 }
952 997
953 /// <summary> 998 /// <summary>
@@ -960,7 +1005,6 @@ namespace OpenSim.Region.Framework.Scenes
960 { 1005 {
961 if (m_shape != null) 1006 if (m_shape != null)
962 { 1007 {
963 StoreUndoState();
964 1008
965 m_shape.Scale = value; 1009 m_shape.Scale = value;
966 1010
@@ -987,6 +1031,7 @@ namespace OpenSim.Region.Framework.Scenes
987 } 1031 }
988 1032
989 public UpdateRequired UpdateFlag { get; set; } 1033 public UpdateRequired UpdateFlag { get; set; }
1034 public bool UpdatePhysRequired { get; set; }
990 1035
991 /// <summary> 1036 /// <summary>
992 /// Used for media on a prim. 1037 /// Used for media on a prim.
@@ -1027,10 +1072,7 @@ namespace OpenSim.Region.Framework.Scenes
1027 { 1072 {
1028 get 1073 get
1029 { 1074 {
1030 if (ParentGroup.IsAttachment) 1075 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1031 return GroupPosition;
1032
1033 return m_offsetPosition + m_groupPosition;
1034 } 1076 }
1035 } 1077 }
1036 1078
@@ -1208,6 +1250,13 @@ namespace OpenSim.Region.Framework.Scenes
1208 _flags = value; 1250 _flags = value;
1209 } 1251 }
1210 } 1252 }
1253
1254 [XmlIgnore]
1255 public bool IsOccupied // KF If an av is sittingon this prim
1256 {
1257 get { return m_occupied; }
1258 set { m_occupied = value; }
1259 }
1211 1260
1212 /// <summary> 1261 /// <summary>
1213 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1262 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1267,6 +1316,316 @@ namespace OpenSim.Region.Framework.Scenes
1267 set { m_collisionSoundVolume = value; } 1316 set { m_collisionSoundVolume = value; }
1268 } 1317 }
1269 1318
1319 public float Buoyancy
1320 {
1321 get
1322 {
1323 if (ParentGroup.RootPart == this)
1324 return m_buoyancy;
1325
1326 return ParentGroup.RootPart.Buoyancy;
1327 }
1328 set
1329 {
1330 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1331 {
1332 ParentGroup.RootPart.Buoyancy = value;
1333 return;
1334 }
1335 m_buoyancy = value;
1336 if (PhysActor != null)
1337 PhysActor.Buoyancy = value;
1338 }
1339 }
1340
1341 public Vector3 Force
1342 {
1343 get
1344 {
1345 if (ParentGroup.RootPart == this)
1346 return m_force;
1347
1348 return ParentGroup.RootPart.Force;
1349 }
1350
1351 set
1352 {
1353 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1354 {
1355 ParentGroup.RootPart.Force = value;
1356 return;
1357 }
1358 m_force = value;
1359 if (PhysActor != null)
1360 PhysActor.Force = value;
1361 }
1362 }
1363
1364 public Vector3 Torque
1365 {
1366 get
1367 {
1368 if (ParentGroup.RootPart == this)
1369 return m_torque;
1370
1371 return ParentGroup.RootPart.Torque;
1372 }
1373
1374 set
1375 {
1376 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1377 {
1378 ParentGroup.RootPart.Torque = value;
1379 return;
1380 }
1381 m_torque = value;
1382 if (PhysActor != null)
1383 PhysActor.Torque = value;
1384 }
1385 }
1386
1387 public byte Material
1388 {
1389 get { return (byte)m_material; }
1390 set
1391 {
1392 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1393 {
1394 bool update = false;
1395
1396 if (m_material != (Material)value)
1397 {
1398 update = true;
1399 m_material = (Material)value;
1400 }
1401
1402 if (m_friction != SOPMaterialData.friction(m_material))
1403 {
1404 update = true;
1405 m_friction = SOPMaterialData.friction(m_material);
1406 }
1407
1408 if (m_bounce != SOPMaterialData.bounce(m_material))
1409 {
1410 update = true;
1411 m_bounce = SOPMaterialData.bounce(m_material);
1412 }
1413
1414 if (update)
1415 {
1416 if (PhysActor != null)
1417 {
1418 PhysActor.SetMaterial((int)value);
1419 }
1420 if(ParentGroup != null)
1421 ParentGroup.HasGroupChanged = true;
1422 ScheduleFullUpdateIfNone();
1423 UpdatePhysRequired = true;
1424 }
1425 }
1426 }
1427 }
1428
1429 // not a propriety to move to methods place later
1430 private bool HasMesh()
1431 {
1432 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1433 return true;
1434 return false;
1435 }
1436
1437 // not a propriety to move to methods place later
1438 public byte DefaultPhysicsShapeType()
1439 {
1440 byte type;
1441
1442 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1443 type = (byte)PhysShapeType.convex;
1444 else
1445 type = (byte)PhysShapeType.prim;
1446
1447 return type;
1448 }
1449
1450 [XmlIgnore]
1451 public bool UsesComplexCost
1452 {
1453 get
1454 {
1455 byte pst = PhysicsShapeType;
1456 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1457 return true;
1458 return false;
1459 }
1460 }
1461
1462 [XmlIgnore]
1463 public float PhysicsCost
1464 {
1465 get
1466 {
1467 if(PhysicsShapeType == (byte)PhysShapeType.none)
1468 return 0;
1469
1470 float cost = 0.1f;
1471 if (PhysActor != null)
1472// cost += PhysActor.Cost;
1473
1474 if ((Flags & PrimFlags.Physics) != 0)
1475 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1476 return cost;
1477 }
1478 }
1479
1480 [XmlIgnore]
1481 public float StreamingCost
1482 {
1483 get
1484 {
1485
1486
1487 return 0.1f;
1488 }
1489 }
1490
1491 [XmlIgnore]
1492 public float SimulationCost
1493 {
1494 get
1495 {
1496 // ignoring scripts. Don't like considering them for this
1497 if((Flags & PrimFlags.Physics) != 0)
1498 return 1.0f;
1499
1500 return 0.5f;
1501 }
1502 }
1503
1504 public byte PhysicsShapeType
1505 {
1506 get { return m_physicsShapeType; }
1507 set
1508 {
1509 byte oldv = m_physicsShapeType;
1510
1511 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1512 {
1513 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1514 m_physicsShapeType = DefaultPhysicsShapeType();
1515 else
1516 m_physicsShapeType = value;
1517 }
1518 else
1519 m_physicsShapeType = DefaultPhysicsShapeType();
1520
1521 if (m_physicsShapeType != oldv && ParentGroup != null)
1522 {
1523 if (m_physicsShapeType == (byte)PhysShapeType.none)
1524 {
1525 if (PhysActor != null)
1526 {
1527 Velocity = new Vector3(0, 0, 0);
1528 Acceleration = new Vector3(0, 0, 0);
1529 if (ParentGroup.RootPart == this)
1530 AngularVelocity = new Vector3(0, 0, 0);
1531 ParentGroup.Scene.RemovePhysicalPrim(1);
1532 RemoveFromPhysics();
1533 }
1534 }
1535 else if (PhysActor == null)
1536 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1537 else
1538 {
1539 PhysActor.PhysicsShapeType = m_physicsShapeType;
1540 if (Shape.SculptEntry)
1541 CheckSculptAndLoad();
1542 }
1543
1544 if (ParentGroup != null)
1545 ParentGroup.HasGroupChanged = true;
1546 }
1547
1548 if (m_physicsShapeType != value)
1549 {
1550 UpdatePhysRequired = true;
1551 }
1552 }
1553 }
1554
1555 public float Density // in kg/m^3
1556 {
1557 get { return m_density; }
1558 set
1559 {
1560 if (value >=1 && value <= 22587.0)
1561 {
1562 m_density = value;
1563 UpdatePhysRequired = true;
1564 }
1565
1566 ScheduleFullUpdateIfNone();
1567
1568 if (ParentGroup != null)
1569 ParentGroup.HasGroupChanged = true;
1570 }
1571 }
1572
1573 public float GravityModifier
1574 {
1575 get { return m_gravitymod; }
1576 set
1577 {
1578 if( value >= -1 && value <=28.0f)
1579 {
1580 m_gravitymod = value;
1581 UpdatePhysRequired = true;
1582 }
1583
1584 ScheduleFullUpdateIfNone();
1585
1586 if (ParentGroup != null)
1587 ParentGroup.HasGroupChanged = true;
1588
1589 }
1590 }
1591
1592 public float Friction
1593 {
1594 get { return m_friction; }
1595 set
1596 {
1597 if (value >= 0 && value <= 255.0f)
1598 {
1599 m_friction = value;
1600 UpdatePhysRequired = true;
1601 }
1602
1603 ScheduleFullUpdateIfNone();
1604
1605 if (ParentGroup != null)
1606 ParentGroup.HasGroupChanged = true;
1607 }
1608 }
1609
1610 public float Bounciness
1611 {
1612 get { return m_bounce; }
1613 set
1614 {
1615 if (value >= 0 && value <= 1.0f)
1616 {
1617 m_bounce = value;
1618 UpdatePhysRequired = true;
1619 }
1620
1621 ScheduleFullUpdateIfNone();
1622
1623 if (ParentGroup != null)
1624 ParentGroup.HasGroupChanged = true;
1625 }
1626 }
1627
1628
1270 #endregion Public Properties with only Get 1629 #endregion Public Properties with only Get
1271 1630
1272 private uint ApplyMask(uint val, bool set, uint mask) 1631 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1432,7 +1791,7 @@ namespace OpenSim.Region.Framework.Scenes
1432 impulse = newimpulse; 1791 impulse = newimpulse;
1433 } 1792 }
1434 1793
1435 ParentGroup.applyAngularImpulse(impulse); 1794 ParentGroup.ApplyAngularImpulse(impulse);
1436 } 1795 }
1437 1796
1438 /// <summary> 1797 /// <summary>
@@ -1442,20 +1801,24 @@ namespace OpenSim.Region.Framework.Scenes
1442 /// </summary> 1801 /// </summary>
1443 /// <param name="impulsei">Vector force</param> 1802 /// <param name="impulsei">Vector force</param>
1444 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1803 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1445 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1804
1805 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1806 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1446 { 1807 {
1447 Vector3 impulse = impulsei; 1808 Vector3 torque = torquei;
1448 1809
1449 if (localGlobalTF) 1810 if (localGlobalTF)
1450 { 1811 {
1812/*
1451 Quaternion grot = GetWorldRotation(); 1813 Quaternion grot = GetWorldRotation();
1452 Quaternion AXgrot = grot; 1814 Quaternion AXgrot = grot;
1453 Vector3 AXimpulsei = impulsei; 1815 Vector3 AXimpulsei = impulsei;
1454 Vector3 newimpulse = AXimpulsei * AXgrot; 1816 Vector3 newimpulse = AXimpulsei * AXgrot;
1455 impulse = newimpulse; 1817 */
1818 torque *= GetWorldRotation();
1456 } 1819 }
1457 1820
1458 ParentGroup.setAngularImpulse(impulse); 1821 Torque = torque;
1459 } 1822 }
1460 1823
1461 /// <summary> 1824 /// <summary>
@@ -1463,17 +1826,23 @@ namespace OpenSim.Region.Framework.Scenes
1463 /// </summary> 1826 /// </summary>
1464 /// <param name="rootObjectFlags"></param> 1827 /// <param name="rootObjectFlags"></param>
1465 /// <param name="VolumeDetectActive"></param> 1828 /// <param name="VolumeDetectActive"></param>
1466 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 1829 /// <param name="building"></param>
1830
1831 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1467 { 1832 {
1833 VolumeDetectActive = _VolumeDetectActive;
1834
1468 if (!ParentGroup.Scene.CollidablePrims) 1835 if (!ParentGroup.Scene.CollidablePrims)
1469 return; 1836 return;
1470 1837
1471// m_log.DebugFormat( 1838 if (PhysicsShapeType == (byte)PhysShapeType.none)
1472// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 1839 return;
1473// Name, LocalId, UUID, m_physicalPrim); 1840
1841 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1842 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1474 1843
1475 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 1844 if (_VolumeDetectActive)
1476 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 1845 isPhantom = true;
1477 1846
1478 if (IsJoint()) 1847 if (IsJoint())
1479 { 1848 {
@@ -1481,22 +1850,11 @@ namespace OpenSim.Region.Framework.Scenes
1481 } 1850 }
1482 else 1851 else
1483 { 1852 {
1484 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 1853 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
1485 if (VolumeDetectActive) 1854 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1486 isPhantom = false; 1855 AddToPhysics(isPhysical, isPhantom, building, true);
1487 1856 else
1488 // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition 1857 PhysActor = null; // just to be sure
1489 // or flexible
1490 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1491 {
1492 // Added clarification.. since A rigid body is an object that you can kick around, etc.
1493 bool rigidBody = isPhysical && !isPhantom;
1494
1495 PhysicsActor pa = AddToPhysics(rigidBody);
1496
1497 if (pa != null)
1498 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1499 }
1500 } 1858 }
1501 } 1859 }
1502 1860
@@ -1548,6 +1906,11 @@ namespace OpenSim.Region.Framework.Scenes
1548 dupe.Category = Category; 1906 dupe.Category = Category;
1549 dupe.m_rezzed = m_rezzed; 1907 dupe.m_rezzed = m_rezzed;
1550 1908
1909 dupe.m_UndoRedo = null;
1910
1911 dupe.IgnoreUndoUpdate = false;
1912 dupe.Undoing = false;
1913
1551 dupe.m_inventory = new SceneObjectPartInventory(dupe); 1914 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1552 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 1915 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1553 1916
@@ -1563,6 +1926,7 @@ namespace OpenSim.Region.Framework.Scenes
1563 1926
1564 // Move afterwards ResetIDs as it clears the localID 1927 // Move afterwards ResetIDs as it clears the localID
1565 dupe.LocalId = localID; 1928 dupe.LocalId = localID;
1929
1566 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1930 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1567 dupe.LastOwnerID = OwnerID; 1931 dupe.LastOwnerID = OwnerID;
1568 1932
@@ -1582,6 +1946,9 @@ namespace OpenSim.Region.Framework.Scenes
1582 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 1946 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1583 } 1947 }
1584 1948
1949 if (dupe.PhysActor != null)
1950 dupe.PhysActor.LocalID = localID;
1951
1585 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 1952 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1586 1953
1587// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 1954// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1701,6 +2068,7 @@ namespace OpenSim.Region.Framework.Scenes
1701 2068
1702 /// <summary> 2069 /// <summary>
1703 /// Do a physics propery update for this part. 2070 /// Do a physics propery update for this part.
2071 /// now also updates phantom and volume detector
1704 /// </summary> 2072 /// </summary>
1705 /// <param name="UsePhysics"></param> 2073 /// <param name="UsePhysics"></param>
1706 /// <param name="isNew"></param> 2074 /// <param name="isNew"></param>
@@ -1723,61 +2091,69 @@ namespace OpenSim.Region.Framework.Scenes
1723 { 2091 {
1724 if (pa.IsPhysical) // implies UsePhysics==false for this block 2092 if (pa.IsPhysical) // implies UsePhysics==false for this block
1725 { 2093 {
1726 if (!isNew) 2094 if (!isNew) // implies UsePhysics==false for this block
2095 {
1727 ParentGroup.Scene.RemovePhysicalPrim(1); 2096 ParentGroup.Scene.RemovePhysicalPrim(1);
1728 2097
1729 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2098 Velocity = new Vector3(0, 0, 0);
1730 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2099 Acceleration = new Vector3(0, 0, 0);
1731 pa.delink(); 2100 if (ParentGroup.RootPart == this)
2101 AngularVelocity = new Vector3(0, 0, 0);
1732 2102
1733 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2103 if (pa.Phantom && !VolumeDetectActive)
1734 { 2104 {
1735 // destroy all joints connected to this now deactivated body 2105 RemoveFromPhysics();
1736 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2106 return;
1737 } 2107 }
1738 2108
1739 // stop client-side interpolation of all joint proxy objects that have just been deleted 2109 pa.IsPhysical = UsePhysics;
1740 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2110 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1741 // which stops client-side interpolation of deactivated joint proxy objects. 2111 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2112 pa.delink();
2113 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2114 {
2115 // destroy all joints connected to this now deactivated body
2116 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2117 }
2118 }
1742 } 2119 }
1743 2120
1744 if (!UsePhysics && !isNew) 2121 if (pa.IsPhysical != UsePhysics)
1745 { 2122 pa.IsPhysical = UsePhysics;
1746 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1747 // prim still has velocity and continues to interpolate its position along the old
1748 // velocity-vector.
1749 Velocity = new Vector3(0, 0, 0);
1750 Acceleration = new Vector3(0, 0, 0);
1751 AngularVelocity = new Vector3(0, 0, 0);
1752 //RotationalVelocity = new Vector3(0, 0, 0);
1753 }
1754 2123
1755 pa.IsPhysical = UsePhysics; 2124 if (UsePhysics)
2125 {
2126 if (ParentGroup.RootPart.KeyframeMotion != null)
2127 ParentGroup.RootPart.KeyframeMotion.Stop();
2128 ParentGroup.RootPart.KeyframeMotion = null;
2129 ParentGroup.Scene.AddPhysicalPrim(1);
1756 2130
1757 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2131 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1758 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2132 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1759 /// that's not wholesome. Had to make Scene public
1760 //PhysActor = null;
1761 2133
1762 if ((Flags & PrimFlags.Phantom) == 0) 2134 if (ParentID != 0 && ParentID != LocalId)
1763 {
1764 if (UsePhysics)
1765 { 2135 {
1766 ParentGroup.Scene.AddPhysicalPrim(1); 2136 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
1767 2137
1768 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 2138 if (parentPa != null)
1769 pa.OnOutOfBounds += PhysicsOutOfBounds;
1770 if (ParentID != 0 && ParentID != LocalId)
1771 { 2139 {
1772 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 2140 pa.link(parentPa);
1773
1774 if (parentPa != null)
1775 {
1776 pa.link(parentPa);
1777 }
1778 } 2141 }
1779 } 2142 }
1780 } 2143 }
2144 }
2145
2146 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2147 if (pa.Phantom != phan)
2148 pa.Phantom = phan;
2149
2150// some engines dont' have this check still
2151// if (VolumeDetectActive != pa.IsVolumeDtc)
2152 {
2153 if (VolumeDetectActive)
2154 pa.SetVolumeDetect(1);
2155 else
2156 pa.SetVolumeDetect(0);
1781 } 2157 }
1782 2158
1783 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2159 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -1896,15 +2272,29 @@ namespace OpenSim.Region.Framework.Scenes
1896 2272
1897 public Vector3 GetGeometricCenter() 2273 public Vector3 GetGeometricCenter()
1898 { 2274 {
1899 PhysicsActor pa = PhysActor; 2275 // this is not real geometric center but a average of positions relative to root prim acording to
1900 2276 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
1901 if (pa != null) 2277 // ignoring tortured prims details since sl also seems to ignore
1902 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); 2278 // so no real use in doing it on physics
1903 else 2279 if (ParentGroup.IsDeleted)
1904 return new Vector3(0, 0, 0); 2280 return new Vector3(0, 0, 0);
2281
2282 return ParentGroup.GetGeometricCenter();
2283
2284 /*
2285 PhysicsActor pa = PhysActor;
2286
2287 if (pa != null)
2288 {
2289 Vector3 vtmp = pa.CenterOfMass;
2290 return vtmp;
2291 }
2292 else
2293 return new Vector3(0, 0, 0);
2294 */
1905 } 2295 }
1906 2296
1907 public float GetMass() 2297 public float GetMass()
1908 { 2298 {
1909 PhysicsActor pa = PhysActor; 2299 PhysicsActor pa = PhysActor;
1910 2300
@@ -1916,12 +2306,7 @@ namespace OpenSim.Region.Framework.Scenes
1916 2306
1917 public Vector3 GetForce() 2307 public Vector3 GetForce()
1918 { 2308 {
1919 PhysicsActor pa = PhysActor; 2309 return Force;
1920
1921 if (pa != null)
1922 return pa.Force;
1923 else
1924 return Vector3.Zero;
1925 } 2310 }
1926 2311
1927 /// <summary> 2312 /// <summary>
@@ -2557,9 +2942,9 @@ namespace OpenSim.Region.Framework.Scenes
2557 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2942 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2558 2943
2559 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2944 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2560 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2945 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2561 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2946 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2562 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2947 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2563 { 2948 {
2564 ParentGroup.AbsolutePosition = newpos; 2949 ParentGroup.AbsolutePosition = newpos;
2565 return; 2950 return;
@@ -2581,17 +2966,18 @@ namespace OpenSim.Region.Framework.Scenes
2581 //Trys to fetch sound id from prim's inventory. 2966 //Trys to fetch sound id from prim's inventory.
2582 //Prim's inventory doesn't support non script items yet 2967 //Prim's inventory doesn't support non script items yet
2583 2968
2584 lock (TaskInventory) 2969 TaskInventory.LockItemsForRead(true);
2970
2971 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2585 { 2972 {
2586 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2973 if (item.Value.Name == sound)
2587 { 2974 {
2588 if (item.Value.Name == sound) 2975 soundID = item.Value.ItemID;
2589 { 2976 break;
2590 soundID = item.Value.ItemID;
2591 break;
2592 }
2593 } 2977 }
2594 } 2978 }
2979
2980 TaskInventory.LockItemsForRead(false);
2595 } 2981 }
2596 2982
2597 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2983 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2714,6 +3100,19 @@ namespace OpenSim.Region.Framework.Scenes
2714 APIDTarget = Quaternion.Identity; 3100 APIDTarget = Quaternion.Identity;
2715 } 3101 }
2716 3102
3103
3104
3105 public void ScheduleFullUpdateIfNone()
3106 {
3107 if (ParentGroup == null)
3108 return;
3109
3110// ??? ParentGroup.HasGroupChanged = true;
3111
3112 if (UpdateFlag != UpdateRequired.FULL)
3113 ScheduleFullUpdate();
3114 }
3115
2717 /// <summary> 3116 /// <summary>
2718 /// Schedules this prim for a full update 3117 /// Schedules this prim for a full update
2719 /// </summary> 3118 /// </summary>
@@ -2915,8 +3314,8 @@ namespace OpenSim.Region.Framework.Scenes
2915 { 3314 {
2916 const float ROTATION_TOLERANCE = 0.01f; 3315 const float ROTATION_TOLERANCE = 0.01f;
2917 const float VELOCITY_TOLERANCE = 0.001f; 3316 const float VELOCITY_TOLERANCE = 0.001f;
2918 const float POSITION_TOLERANCE = 0.05f; 3317 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2919 const int TIME_MS_TOLERANCE = 3000; 3318 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2920 3319
2921 switch (UpdateFlag) 3320 switch (UpdateFlag)
2922 { 3321 {
@@ -2978,17 +3377,16 @@ namespace OpenSim.Region.Framework.Scenes
2978 if (!UUID.TryParse(sound, out soundID)) 3377 if (!UUID.TryParse(sound, out soundID))
2979 { 3378 {
2980 // search sound file from inventory 3379 // search sound file from inventory
2981 lock (TaskInventory) 3380 TaskInventory.LockItemsForRead(true);
3381 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2982 { 3382 {
2983 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3383 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2984 { 3384 {
2985 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3385 soundID = item.Value.ItemID;
2986 { 3386 break;
2987 soundID = item.Value.ItemID;
2988 break;
2989 }
2990 } 3387 }
2991 } 3388 }
3389 TaskInventory.LockItemsForRead(false);
2992 } 3390 }
2993 3391
2994 if (soundID == UUID.Zero) 3392 if (soundID == UUID.Zero)
@@ -3073,10 +3471,13 @@ namespace OpenSim.Region.Framework.Scenes
3073 3471
3074 public void SetBuoyancy(float fvalue) 3472 public void SetBuoyancy(float fvalue)
3075 { 3473 {
3076 PhysicsActor pa = PhysActor; 3474 Buoyancy = fvalue;
3077 3475/*
3078 if (pa != null) 3476 if (PhysActor != null)
3079 pa.Buoyancy = fvalue; 3477 {
3478 PhysActor.Buoyancy = fvalue;
3479 }
3480 */
3080 } 3481 }
3081 3482
3082 public void SetDieAtEdge(bool p) 3483 public void SetDieAtEdge(bool p)
@@ -3092,47 +3493,111 @@ namespace OpenSim.Region.Framework.Scenes
3092 PhysicsActor pa = PhysActor; 3493 PhysicsActor pa = PhysActor;
3093 3494
3094 if (pa != null) 3495 if (pa != null)
3095 pa.FloatOnWater = floatYN == 1; 3496 pa.FloatOnWater = (floatYN == 1);
3096 } 3497 }
3097 3498
3098 public void SetForce(Vector3 force) 3499 public void SetForce(Vector3 force)
3099 { 3500 {
3100 PhysicsActor pa = PhysActor; 3501 Force = force;
3502 }
3101 3503
3102 if (pa != null) 3504 public SOPVehicle sopVehicle
3103 pa.Force = force; 3505 {
3506 get
3507 {
3508 return m_vehicle;
3509 }
3510 set
3511 {
3512 m_vehicle = value;
3513 }
3514 }
3515
3516
3517 public int VehicleType
3518 {
3519 get
3520 {
3521 if (m_vehicle == null)
3522 return (int)Vehicle.TYPE_NONE;
3523 else
3524 return (int)m_vehicle.Type;
3525 }
3526 set
3527 {
3528 SetVehicleType(value);
3529 }
3104 } 3530 }
3105 3531
3106 public void SetVehicleType(int type) 3532 public void SetVehicleType(int type)
3107 { 3533 {
3108 PhysicsActor pa = PhysActor; 3534 m_vehicle = null;
3535
3536 if (type == (int)Vehicle.TYPE_NONE)
3537 {
3538 if (_parentID ==0 && PhysActor != null)
3539 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3540 return;
3541 }
3542 m_vehicle = new SOPVehicle();
3543 m_vehicle.ProcessTypeChange((Vehicle)type);
3544 {
3545 if (_parentID ==0 && PhysActor != null)
3546 PhysActor.VehicleType = type;
3547 return;
3548 }
3549 }
3109 3550
3110 if (pa != null) 3551 public void SetVehicleFlags(int param, bool remove)
3111 pa.VehicleType = type; 3552 {
3553 if (m_vehicle == null)
3554 return;
3555
3556 m_vehicle.ProcessVehicleFlags(param, remove);
3557
3558 if (_parentID ==0 && PhysActor != null)
3559 {
3560 PhysActor.VehicleFlags(param, remove);
3561 }
3112 } 3562 }
3113 3563
3114 public void SetVehicleFloatParam(int param, float value) 3564 public void SetVehicleFloatParam(int param, float value)
3115 { 3565 {
3116 PhysicsActor pa = PhysActor; 3566 if (m_vehicle == null)
3567 return;
3117 3568
3118 if (pa != null) 3569 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
3119 pa.VehicleFloatParam(param, value); 3570
3571 if (_parentID == 0 && PhysActor != null)
3572 {
3573 PhysActor.VehicleFloatParam(param, value);
3574 }
3120 } 3575 }
3121 3576
3122 public void SetVehicleVectorParam(int param, Vector3 value) 3577 public void SetVehicleVectorParam(int param, Vector3 value)
3123 { 3578 {
3124 PhysicsActor pa = PhysActor; 3579 if (m_vehicle == null)
3580 return;
3125 3581
3126 if (pa != null) 3582 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
3127 pa.VehicleVectorParam(param, value); 3583
3584 if (_parentID == 0 && PhysActor != null)
3585 {
3586 PhysActor.VehicleVectorParam(param, value);
3587 }
3128 } 3588 }
3129 3589
3130 public void SetVehicleRotationParam(int param, Quaternion rotation) 3590 public void SetVehicleRotationParam(int param, Quaternion rotation)
3131 { 3591 {
3132 PhysicsActor pa = PhysActor; 3592 if (m_vehicle == null)
3593 return;
3133 3594
3134 if (pa != null) 3595 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
3135 pa.VehicleRotationParam(param, rotation); 3596
3597 if (_parentID == 0 && PhysActor != null)
3598 {
3599 PhysActor.VehicleRotationParam(param, rotation);
3600 }
3136 } 3601 }
3137 3602
3138 /// <summary> 3603 /// <summary>
@@ -3316,13 +3781,6 @@ namespace OpenSim.Region.Framework.Scenes
3316 hasProfileCut = hasDimple; // is it the same thing? 3781 hasProfileCut = hasDimple; // is it the same thing?
3317 } 3782 }
3318 3783
3319 public void SetVehicleFlags(int param, bool remove)
3320 {
3321 if (PhysActor != null)
3322 {
3323 PhysActor.VehicleFlags(param, remove);
3324 }
3325 }
3326 3784
3327 public void SetGroup(UUID groupID, IClientAPI client) 3785 public void SetGroup(UUID groupID, IClientAPI client)
3328 { 3786 {
@@ -3425,68 +3883,18 @@ namespace OpenSim.Region.Framework.Scenes
3425 //ParentGroup.ScheduleGroupForFullUpdate(); 3883 //ParentGroup.ScheduleGroupForFullUpdate();
3426 } 3884 }
3427 3885
3428 public void StoreUndoState() 3886 public void StoreUndoState(ObjectChangeType change)
3429 { 3887 {
3430 StoreUndoState(false); 3888 if (m_UndoRedo == null)
3431 } 3889 m_UndoRedo = new UndoRedoState(5);
3432 3890
3433 public void StoreUndoState(bool forGroup) 3891 lock (m_UndoRedo)
3434 {
3435 if (!Undoing)
3436 { 3892 {
3437 if (!IgnoreUndoUpdate) 3893 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3438 { 3894 {
3439 if (ParentGroup != null) 3895 m_UndoRedo.StoreUndo(this, change);
3440 {
3441 lock (m_undo)
3442 {
3443 if (m_undo.Count > 0)
3444 {
3445 UndoState last = m_undo.Peek();
3446 if (last != null)
3447 {
3448 // TODO: May need to fix for group comparison
3449 if (last.Compare(this))
3450 {
3451 // m_log.DebugFormat(
3452 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3453 // Name, LocalId, m_undo.Count);
3454
3455 return;
3456 }
3457 }
3458 }
3459
3460 // m_log.DebugFormat(
3461 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3462 // Name, LocalId, forGroup, m_undo.Count);
3463
3464 if (ParentGroup.GetSceneMaxUndo() > 0)
3465 {
3466 UndoState nUndo = new UndoState(this, forGroup);
3467
3468 m_undo.Push(nUndo);
3469
3470 if (m_redo.Count > 0)
3471 m_redo.Clear();
3472
3473 // m_log.DebugFormat(
3474 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3475 // Name, LocalId, forGroup, m_undo.Count);
3476 }
3477 }
3478 }
3479 } 3896 }
3480// else
3481// {
3482// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3483// }
3484 } 3897 }
3485// else
3486// {
3487// m_log.DebugFormat(
3488// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3489// }
3490 } 3898 }
3491 3899
3492 /// <summary> 3900 /// <summary>
@@ -3496,84 +3904,46 @@ namespace OpenSim.Region.Framework.Scenes
3496 { 3904 {
3497 get 3905 get
3498 { 3906 {
3499 lock (m_undo) 3907 if (m_UndoRedo == null)
3500 return m_undo.Count; 3908 return 0;
3909 return m_UndoRedo.Count;
3501 } 3910 }
3502 } 3911 }
3503 3912
3504 public void Undo() 3913 public void Undo()
3505 { 3914 {
3506 lock (m_undo) 3915 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3507 { 3916 return;
3508// m_log.DebugFormat(
3509// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3510// Name, LocalId, m_undo.Count);
3511
3512 if (m_undo.Count > 0)
3513 {
3514 UndoState goback = m_undo.Pop();
3515
3516 if (goback != null)
3517 {
3518 UndoState nUndo = null;
3519
3520 if (ParentGroup.GetSceneMaxUndo() > 0)
3521 {
3522 nUndo = new UndoState(this, goback.ForGroup);
3523 }
3524
3525 goback.PlaybackState(this);
3526
3527 if (nUndo != null)
3528 m_redo.Push(nUndo);
3529 }
3530 }
3531 3917
3532// m_log.DebugFormat( 3918 lock (m_UndoRedo)
3533// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3919 {
3534// Name, LocalId, m_undo.Count); 3920 Undoing = true;
3921 m_UndoRedo.Undo(this);
3922 Undoing = false;
3535 } 3923 }
3536 } 3924 }
3537 3925
3538 public void Redo() 3926 public void Redo()
3539 { 3927 {
3540 lock (m_undo) 3928 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3541 { 3929 return;
3542// m_log.DebugFormat(
3543// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3544// Name, LocalId, m_redo.Count);
3545
3546 if (m_redo.Count > 0)
3547 {
3548 UndoState gofwd = m_redo.Pop();
3549
3550 if (gofwd != null)
3551 {
3552 if (ParentGroup.GetSceneMaxUndo() > 0)
3553 {
3554 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3555
3556 m_undo.Push(nUndo);
3557 }
3558
3559 gofwd.PlayfwdState(this);
3560 }
3561 3930
3562// m_log.DebugFormat( 3931 lock (m_UndoRedo)
3563// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3932 {
3564// Name, LocalId, m_redo.Count); 3933 Undoing = true;
3565 } 3934 m_UndoRedo.Redo(this);
3935 Undoing = false;
3566 } 3936 }
3567 } 3937 }
3568 3938
3569 public void ClearUndoState() 3939 public void ClearUndoState()
3570 { 3940 {
3571// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3941 if (m_UndoRedo == null || Undoing)
3942 return;
3572 3943
3573 lock (m_undo) 3944 lock (m_UndoRedo)
3574 { 3945 {
3575 m_undo.Clear(); 3946 m_UndoRedo.Clear();
3576 m_redo.Clear();
3577 } 3947 }
3578 } 3948 }
3579 3949
@@ -4203,6 +4573,27 @@ namespace OpenSim.Region.Framework.Scenes
4203 } 4573 }
4204 } 4574 }
4205 4575
4576
4577 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4578 {
4579 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4580 return;
4581
4582 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4583 {
4584 PhysicsShapeType = (byte)physdata.PhysShapeType;
4585
4586 }
4587
4588 if(Density != physdata.Density)
4589 Density = physdata.Density;
4590 if(GravityModifier != physdata.GravitationModifier)
4591 GravityModifier = physdata.GravitationModifier;
4592 if(Friction != physdata.Friction)
4593 Friction = physdata.Friction;
4594 if(Bounciness != physdata.Bounce)
4595 Bounciness = physdata.Bounce;
4596 }
4206 /// <summary> 4597 /// <summary>
4207 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4598 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
4208 /// </summary> 4599 /// </summary>
@@ -4210,7 +4601,7 @@ namespace OpenSim.Region.Framework.Scenes
4210 /// <param name="SetTemporary"></param> 4601 /// <param name="SetTemporary"></param>
4211 /// <param name="SetPhantom"></param> 4602 /// <param name="SetPhantom"></param>
4212 /// <param name="SetVD"></param> 4603 /// <param name="SetVD"></param>
4213 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4604 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4214 { 4605 {
4215 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4606 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4216 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4607 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -4220,216 +4611,206 @@ namespace OpenSim.Region.Framework.Scenes
4220 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4611 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4221 return; 4612 return;
4222 4613
4223 PhysicsActor pa = PhysActor; 4614 VolumeDetectActive = SetVD;
4224
4225 // Special cases for VD. VD can only be called from a script
4226 // and can't be combined with changes to other states. So we can rely
4227 // that...
4228 // ... if VD is changed, all others are not.
4229 // ... if one of the others is changed, VD is not.
4230 if (SetVD) // VD is active, special logic applies
4231 {
4232 // State machine logic for VolumeDetect
4233 // More logic below
4234 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4235 4615
4236 if (phanReset) // Phantom changes from on to off switch VD off too 4616 // volume detector implies phantom
4237 { 4617 if (VolumeDetectActive)
4238 SetVD = false; // Switch it of for the course of this routine
4239 VolumeDetectActive = false; // and also permanently
4240
4241 if (pa != null)
4242 pa.SetVolumeDetect(0); // Let physics know about it too
4243 }
4244 else
4245 {
4246 // If volumedetect is active we don't want phantom to be applied.
4247 // If this is a new call to VD out of the state "phantom"
4248 // this will also cause the prim to be visible to physics
4249 SetPhantom = false;
4250 }
4251 }
4252
4253 if (UsePhysics && IsJoint())
4254 {
4255 SetPhantom = true; 4618 SetPhantom = true;
4256 }
4257 4619
4258 if (UsePhysics) 4620 if (UsePhysics)
4259 {
4260 AddFlag(PrimFlags.Physics); 4621 AddFlag(PrimFlags.Physics);
4261 if (!wasUsingPhysics)
4262 {
4263 DoPhysicsPropertyUpdate(UsePhysics, false);
4264
4265 if (!ParentGroup.IsDeleted)
4266 {
4267 if (LocalId == ParentGroup.RootPart.LocalId)
4268 {
4269 ParentGroup.CheckSculptAndLoad();
4270 }
4271 }
4272 }
4273 }
4274 else 4622 else
4275 {
4276 RemFlag(PrimFlags.Physics); 4623 RemFlag(PrimFlags.Physics);
4277 if (wasUsingPhysics)
4278 {
4279 DoPhysicsPropertyUpdate(UsePhysics, false);
4280 }
4281 }
4282 4624
4283 if (SetPhantom 4625 if (SetPhantom)
4284 || ParentGroup.IsAttachment
4285 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4286 {
4287 AddFlag(PrimFlags.Phantom); 4626 AddFlag(PrimFlags.Phantom);
4288 4627 else
4289 if (PhysActor != null)
4290 RemoveFromPhysics();
4291 }
4292 else // Not phantom
4293 {
4294 RemFlag(PrimFlags.Phantom); 4628 RemFlag(PrimFlags.Phantom);
4295 4629
4296 if (ParentGroup.Scene == null) 4630 if (SetTemporary)
4297 return; 4631 AddFlag(PrimFlags.TemporaryOnRez);
4632 else
4633 RemFlag(PrimFlags.TemporaryOnRez);
4298 4634
4299 if (ParentGroup.Scene.CollidablePrims && pa == null)
4300 {
4301 pa = AddToPhysics(UsePhysics);
4302 4635
4303 if (pa != null) 4636 if (ParentGroup.Scene == null)
4304 { 4637 return;
4305 pa.SetMaterial(Material);
4306 DoPhysicsPropertyUpdate(UsePhysics, true);
4307
4308 if (!ParentGroup.IsDeleted)
4309 {
4310 if (LocalId == ParentGroup.RootPart.LocalId)
4311 {
4312 ParentGroup.CheckSculptAndLoad();
4313 }
4314 }
4315
4316 if (
4317 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4318 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4319 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4320 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4321 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4322 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4323 (CollisionSound != UUID.Zero)
4324 )
4325 {
4326 pa.OnCollisionUpdate += PhysicsCollision;
4327 pa.SubscribeEvents(1000);
4328 }
4329 }
4330 }
4331 else // it already has a physical representation
4332 {
4333 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4334 4638
4335 if (!ParentGroup.IsDeleted) 4639 PhysicsActor pa = PhysActor;
4336 { 4640
4337 if (LocalId == ParentGroup.RootPart.LocalId) 4641 if (pa != null && building && pa.Building != building)
4338 { 4642 pa.Building = building;
4339 ParentGroup.CheckSculptAndLoad();
4340 }
4341 }
4342 }
4343 }
4344 4643
4345 if (SetVD) 4644 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4645 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4346 { 4646 {
4347 // If the above logic worked (this is urgent candidate to unit tests!)
4348 // we now have a physicsactor.
4349 // Defensive programming calls for a check here.
4350 // Better would be throwing an exception that could be catched by a unit test as the internal
4351 // logic should make sure, this Physactor is always here.
4352 if (pa != null) 4647 if (pa != null)
4353 { 4648 {
4354 pa.SetVolumeDetect(1); 4649 ParentGroup.Scene.RemovePhysicalPrim(1);
4355 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4650 RemoveFromPhysics();
4356 this.VolumeDetectActive = true;
4357 } 4651 }
4652
4653 Velocity = new Vector3(0, 0, 0);
4654 Acceleration = new Vector3(0, 0, 0);
4655 if (ParentGroup.RootPart == this)
4656 AngularVelocity = new Vector3(0, 0, 0);
4358 } 4657 }
4359 else 4658 else
4360 { 4659 {
4361 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4660 if (ParentGroup.Scene.CollidablePrims)
4362 // (mumbles, well, at least if you have infinte CPU powers :-)) 4661 {
4363 if (pa != null) 4662 if (pa == null)
4364 PhysActor.SetVolumeDetect(0); 4663 {
4664 AddToPhysics(UsePhysics, SetPhantom, building , false);
4665 pa = PhysActor;
4365 4666
4366 this.VolumeDetectActive = false; 4667 if (pa != null)
4367 } 4668 {
4669 if (
4670// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4671// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4672// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4673// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4674// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4675// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4676 ((AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
4677// (CollisionSound != UUID.Zero)
4678 )
4679 {
4680 pa.OnCollisionUpdate += PhysicsCollision;
4681 pa.SubscribeEvents(1000);
4682 }
4683 }
4684 }
4368 4685
4369 if (SetTemporary) 4686 else // it already has a physical representation
4370 { 4687 {
4371 AddFlag(PrimFlags.TemporaryOnRez); 4688 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4372 } 4689 /* moved into DoPhysicsPropertyUpdate
4373 else 4690 if(VolumeDetectActive)
4374 { 4691 pa.SetVolumeDetect(1);
4375 RemFlag(PrimFlags.TemporaryOnRez); 4692 else
4376 } 4693 pa.SetVolumeDetect(0);
4694 */
4695 if (pa.Building != building)
4696 pa.Building = building;
4697 }
4698 }
4699 }
4377 4700
4378 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4701 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4379 4702
4703 // and last in case we have a new actor and not building
4704
4380 if (ParentGroup != null) 4705 if (ParentGroup != null)
4381 { 4706 {
4382 ParentGroup.HasGroupChanged = true; 4707 ParentGroup.HasGroupChanged = true;
4383 ScheduleFullUpdate(); 4708 ScheduleFullUpdate();
4384 } 4709 }
4385 4710
4386// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4711// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4387 } 4712 }
4388 4713
4389 /// <summary> 4714 /// <summary>
4390 /// Adds this part to the physics scene. 4715 /// Adds this part to the physics scene.
4716 /// and sets the PhysActor property
4391 /// </summary> 4717 /// </summary>
4392 /// <remarks>This method also sets the PhysActor property.</remarks> 4718 /// <param name="isPhysical">Add this prim as physical.</param>
4393 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4719 /// <param name="isPhantom">Add this prim as phantom.</param>
4394 /// <returns> 4720 /// <param name="building">tells physics to delay full construction of object</param>
4395 /// The physics actor. null if there was a failure. 4721 /// <param name="applyDynamics">applies velocities, force and torque</param>
4396 /// </returns> 4722 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4397 private PhysicsActor AddToPhysics(bool rigidBody) 4723 {
4398 {
4399 PhysicsActor pa; 4724 PhysicsActor pa;
4400 4725
4726 Vector3 velocity = Velocity;
4727 Vector3 rotationalVelocity = AngularVelocity;;
4728
4401 try 4729 try
4402 { 4730 {
4403 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4731 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4404 string.Format("{0}/{1}", Name, UUID), 4732 string.Format("{0}/{1}", Name, UUID),
4405 Shape, 4733 Shape,
4406 AbsolutePosition, 4734 AbsolutePosition,
4407 Scale, 4735 Scale,
4408 RotationOffset, 4736 GetWorldRotation(),
4409 rigidBody, 4737 isPhysical,
4410 m_localId); 4738 isPhantom,
4739 PhysicsShapeType,
4740 m_localId);
4411 } 4741 }
4412 catch 4742 catch (Exception ex)
4413 { 4743 {
4414 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); 4744 m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message);
4415 pa = null; 4745 pa = null;
4416 } 4746 }
4417 4747
4418 // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
4419 // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
4420 // being set.
4421 PhysActor = pa;
4422
4423 // Basic Physics can also return null as well as an exception catch.
4424 if (pa != null) 4748 if (pa != null)
4425 { 4749 {
4426 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4750 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4427 pa.SetMaterial(Material); 4751 pa.SetMaterial(Material);
4428 DoPhysicsPropertyUpdate(rigidBody, true); 4752
4753 if (VolumeDetectActive) // change if not the default only
4754 pa.SetVolumeDetect(1);
4755
4756 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
4757 m_vehicle.SetVehicle(pa);
4758
4759 // we are going to tell rest of code about physics so better have this here
4760 PhysActor = pa;
4761
4762 // DoPhysicsPropertyUpdate(isPhysical, true);
4763 // lets expand it here just with what it really needs to do
4764
4765 if (isPhysical)
4766 {
4767 if (ParentGroup.RootPart.KeyframeMotion != null)
4768 ParentGroup.RootPart.KeyframeMotion.Stop();
4769 ParentGroup.RootPart.KeyframeMotion = null;
4770 ParentGroup.Scene.AddPhysicalPrim(1);
4771
4772 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4773 pa.OnOutOfBounds += PhysicsOutOfBounds;
4774
4775 if (ParentID != 0 && ParentID != LocalId)
4776 {
4777 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4778
4779 if (parentPa != null)
4780 {
4781 pa.link(parentPa);
4782 }
4783 }
4784 }
4785
4786 if (applyDynamics)
4787 // do independent of isphysical so parameters get setted (at least some)
4788 {
4789 Velocity = velocity;
4790 AngularVelocity = rotationalVelocity;
4791 pa.Velocity = velocity;
4792 pa.RotationalVelocity = rotationalVelocity;
4793
4794 // if not vehicle and root part apply force and torque
4795 if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
4796 && LocalId == ParentGroup.RootPart.LocalId)
4797 {
4798 pa.Force = Force;
4799 pa.Torque = Torque;
4800 }
4801 }
4802
4803 if (Shape.SculptEntry)
4804 CheckSculptAndLoad();
4805 else
4806 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4807
4808 if (!building)
4809 pa.Building = false;
4429 } 4810 }
4430 4811
4431 return pa; 4812 PhysActor = pa;
4432 } 4813 }
4433 4814
4434 /// <summary> 4815 /// <summary>
4435 /// This removes the part from the physics scene. 4816 /// This removes the part from the physics scene.
@@ -4636,33 +5017,28 @@ namespace OpenSim.Region.Framework.Scenes
4636 } 5017 }
4637 5018
4638 PhysicsActor pa = PhysActor; 5019 PhysicsActor pa = PhysActor;
4639 5020 if (pa != null)
4640 if (
4641 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4642 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4643 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4644 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4645 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4646 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4647 (CollisionSound != UUID.Zero)
4648 )
4649 { 5021 {
4650 // subscribe to physics updates. 5022 if (
4651 if (pa != null) 5023// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
5024// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
5025// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
5026// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
5027// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
5028// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
5029 ((AggregateScriptEvents & PhyscicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
5030 )
4652 { 5031 {
5032 // subscribe to physics updates.
4653 pa.OnCollisionUpdate += PhysicsCollision; 5033 pa.OnCollisionUpdate += PhysicsCollision;
4654 pa.SubscribeEvents(1000); 5034 pa.SubscribeEvents(1000);
4655 } 5035 }
4656 } 5036 else
4657 else
4658 {
4659 if (pa != null)
4660 { 5037 {
4661 pa.UnSubscribeEvents(); 5038 pa.UnSubscribeEvents();
4662 pa.OnCollisionUpdate -= PhysicsCollision; 5039 pa.OnCollisionUpdate -= PhysicsCollision;
4663 } 5040 }
4664 } 5041 }
4665
4666 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 5042 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4667 //{ 5043 //{
4668 // ParentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting; 5044 // ParentGroup.Scene.EventManager.OnScriptTimerEvent += handleTimerAccounting;
@@ -4789,5 +5165,17 @@ namespace OpenSim.Region.Framework.Scenes
4789 Color color = Color; 5165 Color color = Color;
4790 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5166 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4791 } 5167 }
5168
5169 public void ResetOwnerChangeFlag()
5170 {
5171 List<UUID> inv = Inventory.GetInventoryList();
5172
5173 foreach (UUID itemID in inv)
5174 {
5175 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5176 item.OwnerChanged = false;
5177 Inventory.UpdateInventoryItem(item, false, false);
5178 }
5179 }
4792 } 5180 }
4793} 5181}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index aacad98..36cb09a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,11 +87,14 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -123,38 +129,45 @@ namespace OpenSim.Region.Framework.Scenes
123 public void ResetInventoryIDs() 129 public void ResetInventoryIDs()
124 { 130 {
125 if (null == m_part) 131 if (null == m_part)
126 return; 132 m_items.LockItemsForWrite(true);
127 133
128 lock (m_items) 134 if (Items.Count == 0)
129 { 135 {
130 if (0 == m_items.Count) 136 m_items.LockItemsForWrite(false);
131 return; 137 return;
138 }
132 139
133 IList<TaskInventoryItem> items = GetInventoryItems(); 140 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
134 m_items.Clear(); 141 Items.Clear();
135 142
136 foreach (TaskInventoryItem item in items) 143 foreach (TaskInventoryItem item in items)
137 { 144 {
138 item.ResetIDs(m_part.UUID); 145 item.ResetIDs(m_part.UUID);
139 m_items.Add(item.ItemID, item); 146 Items.Add(item.ItemID, item);
140 }
141 } 147 }
148 m_items.LockItemsForWrite(false);
142 } 149 }
143 150
144 public void ResetObjectID() 151 public void ResetObjectID()
145 { 152 {
146 lock (Items) 153 m_items.LockItemsForWrite(true);
154
155 if (Items.Count == 0)
147 { 156 {
148 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 m_items.LockItemsForWrite(false);
149 Items.Clear(); 158 return;
150
151 foreach (TaskInventoryItem item in items)
152 {
153 item.ParentPartID = m_part.UUID;
154 item.ParentID = m_part.UUID;
155 Items.Add(item.ItemID, item);
156 }
157 } 159 }
160
161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
162 Items.Clear();
163
164 foreach (TaskInventoryItem item in items)
165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
169 }
170 m_items.LockItemsForWrite(false);
158 } 171 }
159 172
160 /// <summary> 173 /// <summary>
@@ -163,12 +176,11 @@ namespace OpenSim.Region.Framework.Scenes
163 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
164 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
165 { 178 {
166 lock (Items) 179 m_items.LockItemsForWrite(true);
180 if (0 == Items.Count)
167 { 181 {
168 if (0 == Items.Count) 182 m_items.LockItemsForWrite(false);
169 { 183 return;
170 return;
171 }
172 } 184 }
173 185
174 HasInventoryChanged = true; 186 HasInventoryChanged = true;
@@ -184,6 +196,7 @@ namespace OpenSim.Region.Framework.Scenes
184 item.PermsGranter = UUID.Zero; 196 item.PermsGranter = UUID.Zero;
185 item.OwnerChanged = true; 197 item.OwnerChanged = true;
186 } 198 }
199 m_items.LockItemsForWrite(false);
187 } 200 }
188 201
189 /// <summary> 202 /// <summary>
@@ -192,12 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
192 /// <param name="groupID"></param> 205 /// <param name="groupID"></param>
193 public void ChangeInventoryGroup(UUID groupID) 206 public void ChangeInventoryGroup(UUID groupID)
194 { 207 {
195 lock (Items) 208 m_items.LockItemsForWrite(true);
209 if (0 == Items.Count)
196 { 210 {
197 if (0 == Items.Count) 211 m_items.LockItemsForWrite(false);
198 { 212 return;
199 return;
200 }
201 } 213 }
202 214
203 // Don't let this set the HasGroupChanged flag for attachments 215 // Don't let this set the HasGroupChanged flag for attachments
@@ -209,12 +221,45 @@ namespace OpenSim.Region.Framework.Scenes
209 m_part.ParentGroup.HasGroupChanged = true; 221 m_part.ParentGroup.HasGroupChanged = true;
210 } 222 }
211 223
212 List<TaskInventoryItem> items = GetInventoryItems(); 224 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
213 foreach (TaskInventoryItem item in items) 225 foreach (TaskInventoryItem item in items)
214 { 226 {
215 if (groupID != item.GroupID) 227 if (groupID != item.GroupID)
228 {
216 item.GroupID = groupID; 229 item.GroupID = groupID;
230 }
231 }
232 m_items.LockItemsForWrite(false);
233 }
234
235 private void QueryScriptStates()
236 {
237 if (m_part == null || m_part.ParentGroup == null)
238 return;
239
240 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
241 if (engines == null) // No engine at all
242 return;
243
244 Items.LockItemsForRead(true);
245 foreach (TaskInventoryItem item in Items.Values)
246 {
247 if (item.InvType == (int)InventoryType.LSL)
248 {
249 foreach (IScriptModule e in engines)
250 {
251 bool running;
252
253 if (e.HasScript(item.ItemID, out running))
254 {
255 item.ScriptRunning = running;
256 break;
257 }
258 }
259 }
217 } 260 }
261
262 Items.LockItemsForRead(false);
218 } 263 }
219 264
220 /// <summary> 265 /// <summary>
@@ -257,7 +302,10 @@ namespace OpenSim.Region.Framework.Scenes
257 { 302 {
258 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL); 303 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
259 foreach (TaskInventoryItem item in scripts) 304 foreach (TaskInventoryItem item in scripts)
305 {
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 306 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
307 m_part.RemoveScriptEvents(item.ItemID);
308 }
261 } 309 }
262 310
263 /// <summary> 311 /// <summary>
@@ -271,7 +319,10 @@ namespace OpenSim.Region.Framework.Scenes
271// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 319// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
272 320
273 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 321 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
322 {
323 StoreScriptError(item.ItemID, "no permission");
274 return; 324 return;
325 }
275 326
276 m_part.AddFlag(PrimFlags.Scripted); 327 m_part.AddFlag(PrimFlags.Scripted);
277 328
@@ -280,14 +331,13 @@ namespace OpenSim.Region.Framework.Scenes
280 if (stateSource == 2 && // Prim crossing 331 if (stateSource == 2 && // Prim crossing
281 m_part.ParentGroup.Scene.m_trustBinaries) 332 m_part.ParentGroup.Scene.m_trustBinaries)
282 { 333 {
283 lock (m_items) 334 m_items.LockItemsForWrite(true);
284 { 335 m_items[item.ItemID].PermsMask = 0;
285 m_items[item.ItemID].PermsMask = 0; 336 m_items[item.ItemID].PermsGranter = UUID.Zero;
286 m_items[item.ItemID].PermsGranter = UUID.Zero; 337 m_items.LockItemsForWrite(false);
287 }
288
289 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 338 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
290 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 339 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
340 StoreScriptErrors(item.ItemID, null);
291 m_part.ParentGroup.AddActiveScriptCount(1); 341 m_part.ParentGroup.AddActiveScriptCount(1);
292 m_part.ScheduleFullUpdate(); 342 m_part.ScheduleFullUpdate();
293 return; 343 return;
@@ -296,6 +346,8 @@ namespace OpenSim.Region.Framework.Scenes
296 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 346 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
297 if (null == asset) 347 if (null == asset)
298 { 348 {
349 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
350 StoreScriptError(item.ItemID, msg);
299 m_log.ErrorFormat( 351 m_log.ErrorFormat(
300 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 352 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
301 item.Name, item.ItemID, m_part.AbsolutePosition, 353 item.Name, item.ItemID, m_part.AbsolutePosition,
@@ -306,16 +358,21 @@ namespace OpenSim.Region.Framework.Scenes
306 if (m_part.ParentGroup.m_savedScriptState != null) 358 if (m_part.ParentGroup.m_savedScriptState != null)
307 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 359 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
308 360
309 lock (m_items) 361 m_items.LockItemsForWrite(true);
310 { 362
311 m_items[item.ItemID].OldItemID = item.OldItemID; 363 m_items[item.ItemID].OldItemID = item.OldItemID;
312 m_items[item.ItemID].PermsMask = 0; 364 m_items[item.ItemID].PermsMask = 0;
313 m_items[item.ItemID].PermsGranter = UUID.Zero; 365 m_items[item.ItemID].PermsGranter = UUID.Zero;
314 }
315 366
367 m_items.LockItemsForWrite(false);
368
316 string script = Utils.BytesToString(asset.Data); 369 string script = Utils.BytesToString(asset.Data);
317 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 370 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
318 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 371 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
372 StoreScriptErrors(item.ItemID, null);
373 if (!item.ScriptRunning)
374 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
375 m_part.LocalId, item.ItemID);
319 m_part.ParentGroup.AddActiveScriptCount(1); 376 m_part.ParentGroup.AddActiveScriptCount(1);
320 m_part.ScheduleFullUpdate(); 377 m_part.ScheduleFullUpdate();
321 } 378 }
@@ -386,20 +443,146 @@ namespace OpenSim.Region.Framework.Scenes
386 443
387 /// <summary> 444 /// <summary>
388 /// Start a script which is in this prim's inventory. 445 /// Start a script which is in this prim's inventory.
446 /// Some processing may occur in the background, but this routine returns asap.
389 /// </summary> 447 /// </summary>
390 /// <param name="itemId"> 448 /// <param name="itemId">
391 /// A <see cref="UUID"/> 449 /// A <see cref="UUID"/>
392 /// </param> 450 /// </param>
393 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 451 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
394 { 452 {
395 TaskInventoryItem item = GetInventoryItem(itemId); 453 lock (m_scriptErrors)
396 if (item != null) 454 {
397 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 455 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
456 m_scriptErrors.Remove(itemId);
457 }
458 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
459 }
460
461 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
462 {
463 m_items.LockItemsForRead(true);
464 if (m_items.ContainsKey(itemId))
465 {
466 if (m_items.ContainsKey(itemId))
467 {
468 m_items.LockItemsForRead(false);
469 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
470 }
471 else
472 {
473 m_items.LockItemsForRead(false);
474 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
475 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
476 StoreScriptError(itemId, msg);
477 m_log.ErrorFormat(
478 "[PRIM INVENTORY]: " +
479 "Couldn't start script with ID {0} since it {1}", itemId, msg);
480 }
481 }
398 else 482 else
483 {
484 m_items.LockItemsForRead(false);
485 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
486 StoreScriptError(itemId, msg);
399 m_log.ErrorFormat( 487 m_log.ErrorFormat(
400 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 488 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
401 itemId, m_part.Name, m_part.UUID, 489 itemId, m_part.Name, m_part.UUID,
402 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 490 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
491 }
492
493 }
494
495 /// <summary>
496 /// Start a script which is in this prim's inventory and return any compilation error messages.
497 /// </summary>
498 /// <param name="itemId">
499 /// A <see cref="UUID"/>
500 /// </param>
501 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
502 {
503 ArrayList errors;
504
505 // Indicate to CreateScriptInstanceInternal() we want it to
506 // post any compilation/loading error messages
507 lock (m_scriptErrors)
508 {
509 m_scriptErrors[itemId] = null;
510 }
511
512 // Perform compilation/loading
513 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
514
515 // Wait for and retrieve any errors
516 lock (m_scriptErrors)
517 {
518 while ((errors = m_scriptErrors[itemId]) == null)
519 {
520 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
521 {
522 m_log.ErrorFormat(
523 "[PRIM INVENTORY]: " +
524 "timedout waiting for script {0} errors", itemId);
525 errors = m_scriptErrors[itemId];
526 if (errors == null)
527 {
528 errors = new ArrayList(1);
529 errors.Add("timedout waiting for errors");
530 }
531 break;
532 }
533 }
534 m_scriptErrors.Remove(itemId);
535 }
536 return errors;
537 }
538
539 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
540 private void StoreScriptErrors(UUID itemId, ArrayList errors)
541 {
542 lock (m_scriptErrors)
543 {
544 // If compilation/loading initiated via CreateScriptInstance(),
545 // it does not want the errors, so just get out
546 if (!m_scriptErrors.ContainsKey(itemId))
547 {
548 return;
549 }
550
551 // Initiated via CreateScriptInstanceEr(), if we know what the
552 // errors are, save them and wake CreateScriptInstanceEr().
553 if (errors != null)
554 {
555 m_scriptErrors[itemId] = errors;
556 System.Threading.Monitor.PulseAll(m_scriptErrors);
557 return;
558 }
559 }
560
561 // Initiated via CreateScriptInstanceEr() but we don't know what
562 // the errors are yet, so retrieve them from the script engine.
563 // This may involve some waiting internal to GetScriptErrors().
564 errors = GetScriptErrors(itemId);
565
566 // Get a default non-null value to indicate success.
567 if (errors == null)
568 {
569 errors = new ArrayList();
570 }
571
572 // Post to CreateScriptInstanceEr() and wake it up
573 lock (m_scriptErrors)
574 {
575 m_scriptErrors[itemId] = errors;
576 System.Threading.Monitor.PulseAll(m_scriptErrors);
577 }
578 }
579
580 // Like StoreScriptErrors(), but just posts a single string message
581 private void StoreScriptError(UUID itemId, string message)
582 {
583 ArrayList errors = new ArrayList(1);
584 errors.Add(message);
585 StoreScriptErrors(itemId, errors);
403 } 586 }
404 587
405 /// <summary> 588 /// <summary>
@@ -412,15 +595,7 @@ namespace OpenSim.Region.Framework.Scenes
412 /// </param> 595 /// </param>
413 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 596 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
414 { 597 {
415 bool scriptPresent = false; 598 if (m_items.ContainsKey(itemId))
416
417 lock (m_items)
418 {
419 if (m_items.ContainsKey(itemId))
420 scriptPresent = true;
421 }
422
423 if (scriptPresent)
424 { 599 {
425 if (!sceneObjectBeingDeleted) 600 if (!sceneObjectBeingDeleted)
426 m_part.RemoveScriptEvents(itemId); 601 m_part.RemoveScriptEvents(itemId);
@@ -445,14 +620,16 @@ namespace OpenSim.Region.Framework.Scenes
445 /// <returns></returns> 620 /// <returns></returns>
446 private bool InventoryContainsName(string name) 621 private bool InventoryContainsName(string name)
447 { 622 {
448 lock (m_items) 623 m_items.LockItemsForRead(true);
624 foreach (TaskInventoryItem item in m_items.Values)
449 { 625 {
450 foreach (TaskInventoryItem item in m_items.Values) 626 if (item.Name == name)
451 { 627 {
452 if (item.Name == name) 628 m_items.LockItemsForRead(false);
453 return true; 629 return true;
454 } 630 }
455 } 631 }
632 m_items.LockItemsForRead(false);
456 return false; 633 return false;
457 } 634 }
458 635
@@ -494,8 +671,9 @@ namespace OpenSim.Region.Framework.Scenes
494 /// <param name="item"></param> 671 /// <param name="item"></param>
495 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 672 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
496 { 673 {
497 List<TaskInventoryItem> il = GetInventoryItems(); 674 m_items.LockItemsForRead(true);
498 675 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
676 m_items.LockItemsForRead(false);
499 foreach (TaskInventoryItem i in il) 677 foreach (TaskInventoryItem i in il)
500 { 678 {
501 if (i.Name == item.Name) 679 if (i.Name == item.Name)
@@ -533,14 +711,14 @@ namespace OpenSim.Region.Framework.Scenes
533 item.Name = name; 711 item.Name = name;
534 item.GroupID = m_part.GroupID; 712 item.GroupID = m_part.GroupID;
535 713
536 lock (m_items) 714 m_items.LockItemsForWrite(true);
537 m_items.Add(item.ItemID, item); 715 m_items.Add(item.ItemID, item);
538 716 m_items.LockItemsForWrite(false);
539 if (allowedDrop) 717 if (allowedDrop)
540 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 718 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
541 else 719 else
542 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 720 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
543 721
544 m_inventorySerial++; 722 m_inventorySerial++;
545 //m_inventorySerial += 2; 723 //m_inventorySerial += 2;
546 HasInventoryChanged = true; 724 HasInventoryChanged = true;
@@ -556,15 +734,15 @@ namespace OpenSim.Region.Framework.Scenes
556 /// <param name="items"></param> 734 /// <param name="items"></param>
557 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 735 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
558 { 736 {
559 lock (m_items) 737 m_items.LockItemsForWrite(true);
738 foreach (TaskInventoryItem item in items)
560 { 739 {
561 foreach (TaskInventoryItem item in items) 740 m_items.Add(item.ItemID, item);
562 { 741// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
563 m_items.Add(item.ItemID, item);
564// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
565 }
566 m_inventorySerial++;
567 } 742 }
743 m_items.LockItemsForWrite(false);
744
745 m_inventorySerial++;
568 } 746 }
569 747
570 /// <summary> 748 /// <summary>
@@ -575,10 +753,9 @@ namespace OpenSim.Region.Framework.Scenes
575 public TaskInventoryItem GetInventoryItem(UUID itemId) 753 public TaskInventoryItem GetInventoryItem(UUID itemId)
576 { 754 {
577 TaskInventoryItem item; 755 TaskInventoryItem item;
578 756 m_items.LockItemsForRead(true);
579 lock (m_items) 757 m_items.TryGetValue(itemId, out item);
580 m_items.TryGetValue(itemId, out item); 758 m_items.LockItemsForRead(false);
581
582 return item; 759 return item;
583 } 760 }
584 761
@@ -594,15 +771,16 @@ namespace OpenSim.Region.Framework.Scenes
594 { 771 {
595 List<TaskInventoryItem> items = new List<TaskInventoryItem>(); 772 List<TaskInventoryItem> items = new List<TaskInventoryItem>();
596 773
597 lock (m_items) 774 m_items.LockItemsForRead(true);
775
776 foreach (TaskInventoryItem item in m_items.Values)
598 { 777 {
599 foreach (TaskInventoryItem item in m_items.Values) 778 if (item.Name == name)
600 { 779 items.Add(item);
601 if (item.Name == name)
602 items.Add(item);
603 }
604 } 780 }
605 781
782 m_items.LockItemsForRead(false);
783
606 return items; 784 return items;
607 } 785 }
608 786
@@ -621,6 +799,9 @@ namespace OpenSim.Region.Framework.Scenes
621 string xmlData = Utils.BytesToString(rezAsset.Data); 799 string xmlData = Utils.BytesToString(rezAsset.Data);
622 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 800 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
623 801
802 group.RootPart.AttachPoint = group.RootPart.Shape.State;
803 group.RootPart.AttachOffset = group.AbsolutePosition;
804
624 group.ResetIDs(); 805 group.ResetIDs();
625 806
626 SceneObjectPart rootPart = group.GetPart(group.UUID); 807 SceneObjectPart rootPart = group.GetPart(group.UUID);
@@ -695,8 +876,9 @@ namespace OpenSim.Region.Framework.Scenes
695 876
696 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 877 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
697 { 878 {
698 TaskInventoryItem it = GetInventoryItem(item.ItemID); 879 m_items.LockItemsForWrite(true);
699 if (it != null) 880
881 if (m_items.ContainsKey(item.ItemID))
700 { 882 {
701// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 883// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
702 884
@@ -709,14 +891,10 @@ namespace OpenSim.Region.Framework.Scenes
709 item.GroupID = m_part.GroupID; 891 item.GroupID = m_part.GroupID;
710 892
711 if (item.AssetID == UUID.Zero) 893 if (item.AssetID == UUID.Zero)
712 item.AssetID = it.AssetID; 894 item.AssetID = m_items[item.ItemID].AssetID;
713 895
714 lock (m_items) 896 m_items[item.ItemID] = item;
715 { 897 m_inventorySerial++;
716 m_items[item.ItemID] = item;
717 m_inventorySerial++;
718 }
719
720 if (fireScriptEvents) 898 if (fireScriptEvents)
721 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 899 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
722 900
@@ -725,7 +903,7 @@ namespace OpenSim.Region.Framework.Scenes
725 HasInventoryChanged = true; 903 HasInventoryChanged = true;
726 m_part.ParentGroup.HasGroupChanged = true; 904 m_part.ParentGroup.HasGroupChanged = true;
727 } 905 }
728 906 m_items.LockItemsForWrite(false);
729 return true; 907 return true;
730 } 908 }
731 else 909 else
@@ -736,8 +914,9 @@ namespace OpenSim.Region.Framework.Scenes
736 item.ItemID, m_part.Name, m_part.UUID, 914 item.ItemID, m_part.Name, m_part.UUID,
737 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 915 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
738 } 916 }
739 return false; 917 m_items.LockItemsForWrite(false);
740 918
919 return false;
741 } 920 }
742 921
743 /// <summary> 922 /// <summary>
@@ -748,43 +927,59 @@ namespace OpenSim.Region.Framework.Scenes
748 /// in this prim's inventory.</returns> 927 /// in this prim's inventory.</returns>
749 public int RemoveInventoryItem(UUID itemID) 928 public int RemoveInventoryItem(UUID itemID)
750 { 929 {
751 TaskInventoryItem item = GetInventoryItem(itemID); 930 m_items.LockItemsForRead(true);
752 if (item != null) 931
932 if (m_items.ContainsKey(itemID))
753 { 933 {
754 int type = m_items[itemID].InvType; 934 int type = m_items[itemID].InvType;
935 m_items.LockItemsForRead(false);
755 if (type == 10) // Script 936 if (type == 10) // Script
756 { 937 {
757 m_part.RemoveScriptEvents(itemID);
758 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 938 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
759 } 939 }
940 m_items.LockItemsForWrite(true);
760 m_items.Remove(itemID); 941 m_items.Remove(itemID);
942 m_items.LockItemsForWrite(false);
761 m_inventorySerial++; 943 m_inventorySerial++;
762 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 944 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
763 945
764 HasInventoryChanged = true; 946 HasInventoryChanged = true;
765 m_part.ParentGroup.HasGroupChanged = true; 947 m_part.ParentGroup.HasGroupChanged = true;
766 948
767 if (!ContainsScripts()) 949 int scriptcount = 0;
950 m_items.LockItemsForRead(true);
951 foreach (TaskInventoryItem item in m_items.Values)
952 {
953 if (item.Type == 10)
954 {
955 scriptcount++;
956 }
957 }
958 m_items.LockItemsForRead(false);
959
960
961 if (scriptcount <= 0)
962 {
768 m_part.RemFlag(PrimFlags.Scripted); 963 m_part.RemFlag(PrimFlags.Scripted);
964 }
769 965
770 m_part.ScheduleFullUpdate(); 966 m_part.ScheduleFullUpdate();
771 967
772 return type; 968 return type;
773
774 } 969 }
775 else 970 else
776 { 971 {
972 m_items.LockItemsForRead(false);
777 m_log.ErrorFormat( 973 m_log.ErrorFormat(
778 "[PRIM INVENTORY]: " + 974 "[PRIM INVENTORY]: " +
779 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 975 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
780 itemID, m_part.Name, m_part.UUID, 976 itemID, m_part.Name, m_part.UUID);
781 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
782 } 977 }
783 978
784 return -1; 979 return -1;
785 } 980 }
786 981
787 private bool CreateInventoryFile() 982 private bool CreateInventoryFileName()
788 { 983 {
789// m_log.DebugFormat( 984// m_log.DebugFormat(
790// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 985// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -793,116 +988,125 @@ namespace OpenSim.Region.Framework.Scenes
793 if (m_inventoryFileName == String.Empty || 988 if (m_inventoryFileName == String.Empty ||
794 m_inventoryFileNameSerial < m_inventorySerial) 989 m_inventoryFileNameSerial < m_inventorySerial)
795 { 990 {
796 // Something changed, we need to create a new file
797 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 991 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
798 m_inventoryFileNameSerial = m_inventorySerial; 992 m_inventoryFileNameSerial = m_inventorySerial;
799 993
800 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 994 return true;
995 }
996
997 return false;
998 }
999
1000 /// <summary>
1001 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1002 /// </summary>
1003 /// <param name="xferManager"></param>
1004 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1005 {
1006 bool changed = CreateInventoryFileName();
1007
1008 bool includeAssets = false;
1009 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1010 includeAssets = true;
1011
1012 if (m_inventoryPrivileged != includeAssets)
1013 changed = true;
1014
1015 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
801 1016
802 lock (m_items) 1017 Items.LockItemsForRead(true);
1018
1019 if (m_inventorySerial == 0) // No inventory
1020 {
1021 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1022 Items.LockItemsForRead(false);
1023 return;
1024 }
1025
1026 if (m_items.Count == 0) // No inventory
1027 {
1028 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1029 Items.LockItemsForRead(false);
1030 return;
1031 }
1032
1033 if (!changed)
1034 {
1035 if (m_inventoryFileData.Length > 2)
803 { 1036 {
804 foreach (TaskInventoryItem item in m_items.Values) 1037 xferManager.AddNewFile(m_inventoryFileName,
805 { 1038 m_inventoryFileData);
806// m_log.DebugFormat( 1039 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
807// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1040 Util.StringToBytes256(m_inventoryFileName));
808// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
809 1041
810 UUID ownerID = item.OwnerID; 1042 Items.LockItemsForRead(false);
811 uint everyoneMask = 0; 1043 return;
812 uint baseMask = item.BasePermissions; 1044 }
813 uint ownerMask = item.CurrentPermissions; 1045 }
814 uint groupMask = item.GroupPermissions;
815 1046
816 invString.AddItemStart(); 1047 m_inventoryPrivileged = includeAssets;
817 invString.AddNameValueLine("item_id", item.ItemID.ToString());
818 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
819 1048
820 invString.AddPermissionsStart(); 1049 foreach (TaskInventoryItem item in m_items.Values)
1050 {
1051 UUID ownerID = item.OwnerID;
1052 uint everyoneMask = 0;
1053 uint baseMask = item.BasePermissions;
1054 uint ownerMask = item.CurrentPermissions;
1055 uint groupMask = item.GroupPermissions;
821 1056
822 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1057 invString.AddItemStart();
823 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1058 invString.AddNameValueLine("item_id", item.ItemID.ToString());
824 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1059 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
825 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
826 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
827 1060
828 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1061 invString.AddPermissionsStart();
829 invString.AddNameValueLine("owner_id", ownerID.ToString());
830 1062
831 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1063 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1064 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1065 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1066 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1067 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
832 1068
833 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1069 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
834 invString.AddSectionEnd(); 1070 invString.AddNameValueLine("owner_id", ownerID.ToString());
835 1071
836 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1072 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
837 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
838 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
839 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
840 1073
841 invString.AddSaleStart(); 1074 invString.AddNameValueLine("group_id", item.GroupID.ToString());
842 invString.AddNameValueLine("sale_type", "not"); 1075 invString.AddSectionEnd();
843 invString.AddNameValueLine("sale_price", "0");
844 invString.AddSectionEnd();
845 1076
846 invString.AddNameValueLine("name", item.Name + "|"); 1077 if (includeAssets)
847 invString.AddNameValueLine("desc", item.Description + "|"); 1078 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1079 else
1080 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1081 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1082 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1083 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
848 1084
849 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1085 invString.AddSaleStart();
850 invString.AddSectionEnd(); 1086 invString.AddNameValueLine("sale_type", "not");
851 } 1087 invString.AddNameValueLine("sale_price", "0");
852 } 1088 invString.AddSectionEnd();
853 1089
854 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1090 invString.AddNameValueLine("name", item.Name + "|");
1091 invString.AddNameValueLine("desc", item.Description + "|");
855 1092
856 return true; 1093 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1094 invString.AddSectionEnd();
857 } 1095 }
858 1096
859 // No need to recreate, the existing file is fine 1097 Items.LockItemsForRead(false);
860 return false;
861 }
862 1098
863 /// <summary> 1099 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
864 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
865 /// </summary>
866 /// <param name="xferManager"></param>
867 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
868 {
869 lock (m_items)
870 {
871 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
872 // a new script if any previous deletion has left the prim inventory empty.
873 if (m_items.Count == 0) // No inventory
874 {
875// m_log.DebugFormat(
876// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
877// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
878
879 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
880 return;
881 }
882 1100
883 CreateInventoryFile(); 1101 if (m_inventoryFileData.Length > 2)
884 1102 {
885 // In principle, we should only do the rest if the inventory changed; 1103 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
886 // by sending m_inventorySerial to the client, it ought to know 1104 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
887 // that nothing changed and that it doesn't need to request the file. 1105 Util.StringToBytes256(m_inventoryFileName));
888 // Unfortunately, it doesn't look like the client optimizes this; 1106 return;
889 // the client seems to always come back and request the Xfer,
890 // no matter what value m_inventorySerial has.
891 // FIXME: Could probably be > 0 here rather than > 2
892 if (m_inventoryFileData.Length > 2)
893 {
894 // Add the file for Xfer
895 // m_log.DebugFormat(
896 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
897 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
898
899 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
900 }
901
902 // Tell the client we're ready to Xfer the file
903 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
904 Util.StringToBytes256(m_inventoryFileName));
905 } 1107 }
1108
1109 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
906 } 1110 }
907 1111
908 /// <summary> 1112 /// <summary>
@@ -911,13 +1115,19 @@ namespace OpenSim.Region.Framework.Scenes
911 /// <param name="datastore"></param> 1115 /// <param name="datastore"></param>
912 public void ProcessInventoryBackup(ISimulationDataService datastore) 1116 public void ProcessInventoryBackup(ISimulationDataService datastore)
913 { 1117 {
914 if (HasInventoryChanged) 1118// Removed this because linking will cause an immediate delete of the new
915 { 1119// child prim from the database and the subsequent storing of the prim sees
916 HasInventoryChanged = false; 1120// the inventory of it as unchanged and doesn't store it at all. The overhead
917 List<TaskInventoryItem> items = GetInventoryItems(); 1121// of storing prim inventory needlessly is much less than the aggravation
918 datastore.StorePrimInventory(m_part.UUID, items); 1122// of prim inventory loss.
1123// if (HasInventoryChanged)
1124// {
1125 Items.LockItemsForRead(true);
1126 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1127 Items.LockItemsForRead(false);
919 1128
920 } 1129 HasInventoryChanged = false;
1130// }
921 } 1131 }
922 1132
923 public class InventoryStringBuilder 1133 public class InventoryStringBuilder
@@ -983,82 +1193,63 @@ namespace OpenSim.Region.Framework.Scenes
983 { 1193 {
984 uint mask=0x7fffffff; 1194 uint mask=0x7fffffff;
985 1195
986 lock (m_items) 1196 foreach (TaskInventoryItem item in m_items.Values)
987 { 1197 {
988 foreach (TaskInventoryItem item in m_items.Values) 1198 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1199 mask &= ~((uint)PermissionMask.Copy >> 13);
1200 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1201 mask &= ~((uint)PermissionMask.Transfer >> 13);
1202 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1203 mask &= ~((uint)PermissionMask.Modify >> 13);
1204
1205 if (item.InvType == (int)InventoryType.Object)
989 { 1206 {
990 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1207 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
991 mask &= ~((uint)PermissionMask.Copy >> 13); 1208 mask &= ~((uint)PermissionMask.Copy >> 13);
992 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1209 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
993 mask &= ~((uint)PermissionMask.Transfer >> 13); 1210 mask &= ~((uint)PermissionMask.Transfer >> 13);
994 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1211 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
995 mask &= ~((uint)PermissionMask.Modify >> 13); 1212 mask &= ~((uint)PermissionMask.Modify >> 13);
996
997 if (item.InvType != (int)InventoryType.Object)
998 {
999 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1000 mask &= ~((uint)PermissionMask.Copy >> 13);
1001 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1002 mask &= ~((uint)PermissionMask.Transfer >> 13);
1003 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1004 mask &= ~((uint)PermissionMask.Modify >> 13);
1005 }
1006 else
1007 {
1008 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1009 mask &= ~((uint)PermissionMask.Copy >> 13);
1010 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1011 mask &= ~((uint)PermissionMask.Transfer >> 13);
1012 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1013 mask &= ~((uint)PermissionMask.Modify >> 13);
1014 }
1015
1016 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1017 mask &= ~(uint)PermissionMask.Copy;
1018 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1019 mask &= ~(uint)PermissionMask.Transfer;
1020 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1021 mask &= ~(uint)PermissionMask.Modify;
1022 } 1213 }
1214
1215 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1216 mask &= ~(uint)PermissionMask.Copy;
1217 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1218 mask &= ~(uint)PermissionMask.Transfer;
1219 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1220 mask &= ~(uint)PermissionMask.Modify;
1023 } 1221 }
1024
1025 return mask; 1222 return mask;
1026 } 1223 }
1027 1224
1028 public void ApplyNextOwnerPermissions() 1225 public void ApplyNextOwnerPermissions()
1029 { 1226 {
1030 lock (m_items) 1227 foreach (TaskInventoryItem item in m_items.Values)
1031 { 1228 {
1032 foreach (TaskInventoryItem item in m_items.Values) 1229 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1033 { 1230 {
1034 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1231 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1035 { 1232 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1036 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1233 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1037 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1234 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1038 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1235 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1039 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1236 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1040 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1041 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1042 }
1043 item.CurrentPermissions &= item.NextPermissions;
1044 item.BasePermissions &= item.NextPermissions;
1045 item.EveryonePermissions &= item.NextPermissions;
1046 item.OwnerChanged = true;
1047 item.PermsMask = 0;
1048 item.PermsGranter = UUID.Zero;
1049 } 1237 }
1238 item.OwnerChanged = true;
1239 item.CurrentPermissions &= item.NextPermissions;
1240 item.BasePermissions &= item.NextPermissions;
1241 item.EveryonePermissions &= item.NextPermissions;
1242 item.PermsMask = 0;
1243 item.PermsGranter = UUID.Zero;
1050 } 1244 }
1051 } 1245 }
1052 1246
1053 public void ApplyGodPermissions(uint perms) 1247 public void ApplyGodPermissions(uint perms)
1054 { 1248 {
1055 lock (m_items) 1249 foreach (TaskInventoryItem item in m_items.Values)
1056 { 1250 {
1057 foreach (TaskInventoryItem item in m_items.Values) 1251 item.CurrentPermissions = perms;
1058 { 1252 item.BasePermissions = perms;
1059 item.CurrentPermissions = perms;
1060 item.BasePermissions = perms;
1061 }
1062 } 1253 }
1063 1254
1064 m_inventorySerial++; 1255 m_inventorySerial++;
@@ -1071,14 +1262,11 @@ namespace OpenSim.Region.Framework.Scenes
1071 /// <returns></returns> 1262 /// <returns></returns>
1072 public bool ContainsScripts() 1263 public bool ContainsScripts()
1073 { 1264 {
1074 lock (m_items) 1265 foreach (TaskInventoryItem item in m_items.Values)
1075 { 1266 {
1076 foreach (TaskInventoryItem item in m_items.Values) 1267 if (item.InvType == (int)InventoryType.LSL)
1077 { 1268 {
1078 if (item.InvType == (int)InventoryType.LSL) 1269 return true;
1079 {
1080 return true;
1081 }
1082 } 1270 }
1083 } 1271 }
1084 1272
@@ -1092,17 +1280,15 @@ namespace OpenSim.Region.Framework.Scenes
1092 public int ScriptCount() 1280 public int ScriptCount()
1093 { 1281 {
1094 int count = 0; 1282 int count = 0;
1095 lock (m_items) 1283 Items.LockItemsForRead(true);
1284 foreach (TaskInventoryItem item in m_items.Values)
1096 { 1285 {
1097 foreach (TaskInventoryItem item in m_items.Values) 1286 if (item.InvType == (int)InventoryType.LSL)
1098 { 1287 {
1099 if (item.InvType == (int)InventoryType.LSL) 1288 count++;
1100 {
1101 count++;
1102 }
1103 } 1289 }
1104 } 1290 }
1105 1291 Items.LockItemsForRead(false);
1106 return count; 1292 return count;
1107 } 1293 }
1108 /// <summary> 1294 /// <summary>
@@ -1138,11 +1324,8 @@ namespace OpenSim.Region.Framework.Scenes
1138 { 1324 {
1139 List<UUID> ret = new List<UUID>(); 1325 List<UUID> ret = new List<UUID>();
1140 1326
1141 lock (m_items) 1327 foreach (TaskInventoryItem item in m_items.Values)
1142 { 1328 ret.Add(item.ItemID);
1143 foreach (TaskInventoryItem item in m_items.Values)
1144 ret.Add(item.ItemID);
1145 }
1146 1329
1147 return ret; 1330 return ret;
1148 } 1331 }
@@ -1151,8 +1334,9 @@ namespace OpenSim.Region.Framework.Scenes
1151 { 1334 {
1152 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1335 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1153 1336
1154 lock (m_items) 1337 Items.LockItemsForRead(true);
1155 ret = new List<TaskInventoryItem>(m_items.Values); 1338 ret = new List<TaskInventoryItem>(m_items.Values);
1339 Items.LockItemsForRead(false);
1156 1340
1157 return ret; 1341 return ret;
1158 } 1342 }
@@ -1161,18 +1345,24 @@ namespace OpenSim.Region.Framework.Scenes
1161 { 1345 {
1162 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1346 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1163 1347
1164 lock (m_items) 1348 Items.LockItemsForRead(true);
1165 { 1349
1166 foreach (TaskInventoryItem item in m_items.Values) 1350 foreach (TaskInventoryItem item in m_items.Values)
1167 if (item.InvType == (int)type) 1351 if (item.InvType == (int)type)
1168 ret.Add(item); 1352 ret.Add(item);
1169 } 1353
1354 Items.LockItemsForRead(false);
1170 1355
1171 return ret; 1356 return ret;
1172 } 1357 }
1173 1358
1174 public Dictionary<UUID, string> GetScriptStates() 1359 public Dictionary<UUID, string> GetScriptStates()
1175 { 1360 {
1361 return GetScriptStates(false);
1362 }
1363
1364 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1365 {
1176 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1366 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1177 1367
1178 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1368 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1194,14 +1384,21 @@ namespace OpenSim.Region.Framework.Scenes
1194 string n = e.GetXMLState(item.ItemID); 1384 string n = e.GetXMLState(item.ItemID);
1195 if (n != String.Empty) 1385 if (n != String.Empty)
1196 { 1386 {
1197 if (!ret.ContainsKey(item.ItemID)) 1387 if (oldIDs)
1198 ret[item.ItemID] = n; 1388 {
1389 if (!ret.ContainsKey(item.OldItemID))
1390 ret[item.OldItemID] = n;
1391 }
1392 else
1393 {
1394 if (!ret.ContainsKey(item.ItemID))
1395 ret[item.ItemID] = n;
1396 }
1199 break; 1397 break;
1200 } 1398 }
1201 } 1399 }
1202 } 1400 }
1203 } 1401 }
1204
1205 return ret; 1402 return ret;
1206 } 1403 }
1207 1404
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index b5f789b..ac791ae 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Scenes
92 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 92 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
93 /// issue #1716 93 /// issue #1716
94 /// </summary> 94 /// </summary>
95 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); 95 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
96 96
97 /// <summary> 97 /// <summary>
98 /// Movement updates for agents in neighboring regions are sent directly to clients. 98 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -169,6 +169,7 @@ namespace OpenSim.Region.Framework.Scenes
169// private int m_lastColCount = -1; //KF: Look for Collision chnages 169// private int m_lastColCount = -1; //KF: Look for Collision chnages
170// private int m_updateCount = 0; //KF: Update Anims for a while 170// private int m_updateCount = 0; //KF: Update Anims for a while
171// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 171// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
172 private List<uint> m_lastColliders = new List<uint>();
172 173
173 private TeleportFlags m_teleportFlags; 174 private TeleportFlags m_teleportFlags;
174 public TeleportFlags TeleportFlags 175 public TeleportFlags TeleportFlags
@@ -230,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes
230 //private int m_moveToPositionStateStatus; 231 //private int m_moveToPositionStateStatus;
231 //***************************************************** 232 //*****************************************************
232 233
234 private bool m_collisionEventFlag = false;
235 private object m_collisionEventLock = new Object();
236
237 private int m_movementAnimationUpdateCounter = 0;
238
239 private Vector3 m_prevSitOffset;
240
233 protected AvatarAppearance m_appearance; 241 protected AvatarAppearance m_appearance;
234 242
235 public AvatarAppearance Appearance 243 public AvatarAppearance Appearance
@@ -569,6 +577,13 @@ namespace OpenSim.Region.Framework.Scenes
569 /// </summary> 577 /// </summary>
570 public uint ParentID { get; set; } 578 public uint ParentID { get; set; }
571 579
580 public UUID ParentUUID
581 {
582 get { return m_parentUUID; }
583 set { m_parentUUID = value; }
584 }
585 private UUID m_parentUUID = UUID.Zero;
586
572 /// <summary> 587 /// <summary>
573 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null. 588 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
574 /// </summary> 589 /// </summary>
@@ -729,6 +744,26 @@ namespace OpenSim.Region.Framework.Scenes
729 Appearance = appearance; 744 Appearance = appearance;
730 } 745 }
731 746
747 private void RegionHeartbeatEnd(Scene scene)
748 {
749 if (IsChildAgent)
750 return;
751
752 m_movementAnimationUpdateCounter ++;
753 if (m_movementAnimationUpdateCounter >= 2)
754 {
755 m_movementAnimationUpdateCounter = 0;
756 if (Animator != null && ParentID == 0) // skip it if sitting
757 {
758 Animator.UpdateMovementAnimations();
759 }
760 else
761 {
762 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
763 }
764 }
765 }
766
732 public void RegisterToEvents() 767 public void RegisterToEvents()
733 { 768 {
734 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 769 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
@@ -798,10 +833,38 @@ namespace OpenSim.Region.Framework.Scenes
798 "[SCENE]: Upgrading child to root agent for {0} in {1}", 833 "[SCENE]: Upgrading child to root agent for {0} in {1}",
799 Name, m_scene.RegionInfo.RegionName); 834 Name, m_scene.RegionInfo.RegionName);
800 835
801 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
802
803 bool wasChild = IsChildAgent; 836 bool wasChild = IsChildAgent;
804 IsChildAgent = false; 837
838 if (ParentUUID != UUID.Zero)
839 {
840 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
841 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
842 if (part == null)
843 {
844 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
845 }
846 else
847 {
848 part.ParentGroup.AddAvatar(UUID);
849 if (part.SitTargetPosition != Vector3.Zero)
850 part.SitTargetAvatar = UUID;
851 ParentPosition = part.GetWorldPosition();
852 ParentID = part.LocalId;
853 ParentPart = part;
854 m_pos = m_prevSitOffset;
855 pos = ParentPosition;
856 }
857 ParentUUID = UUID.Zero;
858
859 IsChildAgent = false;
860
861 Animator.TrySetMovementAnimation("SIT");
862 }
863 else
864 {
865 IsChildAgent = false;
866 }
867
805 868
806 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 869 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
807 if (gm != null) 870 if (gm != null)
@@ -811,62 +874,64 @@ namespace OpenSim.Region.Framework.Scenes
811 874
812 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 875 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
813 876
814 // Moved this from SendInitialData to ensure that Appearance is initialized 877 if (ParentID == 0)
815 // before the inventory is processed in MakeRootAgent. This fixes a race condition
816 // related to the handling of attachments
817 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
818 if (m_scene.TestBorderCross(pos, Cardinals.E))
819 { 878 {
820 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 879 // Moved this from SendInitialData to ensure that Appearance is initialized
821 pos.X = crossedBorder.BorderLine.Z - 1; 880 // before the inventory is processed in MakeRootAgent. This fixes a race condition
822 } 881 // related to the handling of attachments
882 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
883 if (m_scene.TestBorderCross(pos, Cardinals.E))
884 {
885 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
886 pos.X = crossedBorder.BorderLine.Z - 1;
887 }
823 888
824 if (m_scene.TestBorderCross(pos, Cardinals.N)) 889 if (m_scene.TestBorderCross(pos, Cardinals.N))
825 { 890 {
826 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 891 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
827 pos.Y = crossedBorder.BorderLine.Z - 1; 892 pos.Y = crossedBorder.BorderLine.Z - 1;
828 } 893 }
829 894
830 CheckAndAdjustLandingPoint(ref pos); 895 CheckAndAdjustLandingPoint(ref pos);
831 896
832 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 897 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
833 { 898 {
834 m_log.WarnFormat( 899 m_log.WarnFormat(
835 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 900 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
836 pos, Name, UUID); 901 pos, Name, UUID);
837 902
838 if (pos.X < 0f) pos.X = 0f; 903 if (pos.X < 0f) pos.X = 0f;
839 if (pos.Y < 0f) pos.Y = 0f; 904 if (pos.Y < 0f) pos.Y = 0f;
840 if (pos.Z < 0f) pos.Z = 0f; 905 if (pos.Z < 0f) pos.Z = 0f;
841 } 906 }
842 907
843 float localAVHeight = 1.56f; 908 float localAVHeight = 1.56f;
844 if (Appearance.AvatarHeight > 0) 909 if (Appearance.AvatarHeight > 0)
845 localAVHeight = Appearance.AvatarHeight; 910 localAVHeight = Appearance.AvatarHeight;
846 911
847 float posZLimit = 0; 912 float posZLimit = 0;
848 913
849 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 914 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
850 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 915 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
851 916
852 float newPosZ = posZLimit + localAVHeight / 2; 917 float newPosZ = posZLimit + localAVHeight / 2;
853 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 918 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
854 { 919 {
855 pos.Z = newPosZ; 920 pos.Z = newPosZ;
856 } 921 }
857 AbsolutePosition = pos; 922 AbsolutePosition = pos;
858 923
859 AddToPhysicalScene(isFlying); 924 AddToPhysicalScene(isFlying);
860 925
861 if (ForceFly) 926 if (ForceFly)
862 { 927 {
863 Flying = true; 928 Flying = true;
864 } 929 }
865 else if (FlyDisabled) 930 else if (FlyDisabled)
866 { 931 {
867 Flying = false; 932 Flying = false;
933 }
868 } 934 }
869
870 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 935 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
871 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 936 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
872 // elsewhere anyway 937 // elsewhere anyway
@@ -884,14 +949,19 @@ namespace OpenSim.Region.Framework.Scenes
884 { 949 {
885 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 950 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
886 // Resume scripts 951 // Resume scripts
887 foreach (SceneObjectGroup sog in m_attachments) 952 Util.FireAndForget(delegate(object x) {
888 { 953 foreach (SceneObjectGroup sog in m_attachments)
889 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 954 {
890 sog.ResumeScripts(); 955 sog.ScheduleGroupForFullUpdate();
891 } 956 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
957 sog.ResumeScripts();
958 }
959 });
892 } 960 }
893 } 961 }
894 962
963 SendAvatarDataToAllAgents();
964
895 // send the animations of the other presences to me 965 // send the animations of the other presences to me
896 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) 966 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
897 { 967 {
@@ -905,6 +975,8 @@ namespace OpenSim.Region.Framework.Scenes
905 MovementFlag = 0; 975 MovementFlag = 0;
906 976
907 m_scene.EventManager.TriggerOnMakeRootAgent(this); 977 m_scene.EventManager.TriggerOnMakeRootAgent(this);
978
979 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
908 } 980 }
909 981
910 public int GetStateSource() 982 public int GetStateSource()
@@ -932,6 +1004,8 @@ namespace OpenSim.Region.Framework.Scenes
932 /// </remarks> 1004 /// </remarks>
933 public void MakeChildAgent() 1005 public void MakeChildAgent()
934 { 1006 {
1007 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1008
935 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1009 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName);
936 1010
937 // Reset these so that teleporting in and walking out isn't seen 1011 // Reset these so that teleporting in and walking out isn't seen
@@ -1002,11 +1076,24 @@ namespace OpenSim.Region.Framework.Scenes
1002 1076
1003 public void TeleportWithMomentum(Vector3 pos) 1077 public void TeleportWithMomentum(Vector3 pos)
1004 { 1078 {
1079 TeleportWithMomentum(pos, null);
1080 }
1081
1082 public void TeleportWithMomentum(Vector3 pos, Vector3? v)
1083 {
1005 bool isFlying = Flying; 1084 bool isFlying = Flying;
1085 Vector3 vel = Velocity;
1006 RemoveFromPhysicalScene(); 1086 RemoveFromPhysicalScene();
1007 CheckLandingPoint(ref pos); 1087 CheckLandingPoint(ref pos);
1008 AbsolutePosition = pos; 1088 AbsolutePosition = pos;
1009 AddToPhysicalScene(isFlying); 1089 AddToPhysicalScene(isFlying);
1090 if (PhysicsActor != null)
1091 {
1092 if (v.HasValue)
1093 PhysicsActor.SetMomentum((Vector3)v);
1094 else
1095 PhysicsActor.SetMomentum(vel);
1096 }
1010 1097
1011 SendTerseUpdateToAllClients(); 1098 SendTerseUpdateToAllClients();
1012 } 1099 }
@@ -1311,8 +1398,16 @@ namespace OpenSim.Region.Framework.Scenes
1311 { 1398 {
1312 if (m_followCamAuto) 1399 if (m_followCamAuto)
1313 { 1400 {
1314 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; 1401 // Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
1315 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); 1402 // m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
1403 Vector3 posAdjusted = AbsolutePosition + HEAD_ADJUSTMENT;
1404 Vector3 distTocam = CameraPosition - posAdjusted;
1405 float distTocamlen = distTocam.Length();
1406 if (distTocamlen > 0)
1407 {
1408 distTocam *= 1.0f / distTocamlen;
1409 m_scene.PhysicsScene.RaycastWorld(posAdjusted, distTocam, distTocamlen + 0.3f, RayCastCameraCallback);
1410 }
1316 } 1411 }
1317 } 1412 }
1318 1413
@@ -1689,9 +1784,9 @@ namespace OpenSim.Region.Framework.Scenes
1689 if (pos.Z - terrainHeight < 0.2) 1784 if (pos.Z - terrainHeight < 0.2)
1690 pos.Z = terrainHeight; 1785 pos.Z = terrainHeight;
1691 1786
1692 m_log.DebugFormat( 1787// m_log.DebugFormat(
1693 "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 1788// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
1694 Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 1789// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
1695 1790
1696 if (noFly) 1791 if (noFly)
1697 Flying = false; 1792 Flying = false;
@@ -1748,8 +1843,11 @@ namespace OpenSim.Region.Framework.Scenes
1748// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 1843// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
1749 1844
1750 SitGround = false; 1845 SitGround = false;
1846
1847/* move this down so avatar gets physical in the new position and not where it is siting
1751 if (PhysicsActor == null) 1848 if (PhysicsActor == null)
1752 AddToPhysicalScene(false); 1849 AddToPhysicalScene(false);
1850 */
1753 1851
1754 if (ParentID != 0) 1852 if (ParentID != 0)
1755 { 1853 {
@@ -1773,6 +1871,7 @@ namespace OpenSim.Region.Framework.Scenes
1773 if (part.SitTargetAvatar == UUID) 1871 if (part.SitTargetAvatar == UUID)
1774 part.SitTargetAvatar = UUID.Zero; 1872 part.SitTargetAvatar = UUID.Zero;
1775 1873
1874 part.ParentGroup.DeleteAvatar(UUID);
1776 ParentPosition = part.GetWorldPosition(); 1875 ParentPosition = part.GetWorldPosition();
1777 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1876 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1778 1877
@@ -1781,6 +1880,10 @@ namespace OpenSim.Region.Framework.Scenes
1781 1880
1782 ParentID = 0; 1881 ParentID = 0;
1783 ParentPart = null; 1882 ParentPart = null;
1883
1884 if (PhysicsActor == null)
1885 AddToPhysicalScene(false);
1886
1784 SendAvatarDataToAllAgents(); 1887 SendAvatarDataToAllAgents();
1785 m_requestedSitTargetID = 0; 1888 m_requestedSitTargetID = 0;
1786 1889
@@ -1788,6 +1891,9 @@ namespace OpenSim.Region.Framework.Scenes
1788 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 1891 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1789 } 1892 }
1790 1893
1894 else if (PhysicsActor == null)
1895 AddToPhysicalScene(false);
1896
1791 Animator.TrySetMovementAnimation("STAND"); 1897 Animator.TrySetMovementAnimation("STAND");
1792 } 1898 }
1793 1899
@@ -1911,7 +2017,7 @@ namespace OpenSim.Region.Framework.Scenes
1911 forceMouselook = part.GetForceMouselook(); 2017 forceMouselook = part.GetForceMouselook();
1912 2018
1913 ControllingClient.SendSitResponse( 2019 ControllingClient.SendSitResponse(
1914 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2020 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1915 2021
1916 m_requestedSitTargetUUID = targetID; 2022 m_requestedSitTargetUUID = targetID;
1917 2023
@@ -2193,14 +2299,36 @@ namespace OpenSim.Region.Framework.Scenes
2193 2299
2194 //Quaternion result = (sitTargetOrient * vq) * nq; 2300 //Quaternion result = (sitTargetOrient * vq) * nq;
2195 2301
2196 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2302 double x, y, z, m;
2303
2304 Quaternion r = sitTargetOrient;
2305 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2306
2307 if (Math.Abs(1.0 - m) > 0.000001)
2308 {
2309 m = 1.0 / Math.Sqrt(m);
2310 r.X *= (float)m;
2311 r.Y *= (float)m;
2312 r.Z *= (float)m;
2313 r.W *= (float)m;
2314 }
2315
2316 x = 2 * (r.X * r.Z + r.Y * r.W);
2317 y = 2 * (-r.X * r.W + r.Y * r.Z);
2318 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2319
2320 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2321 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2322 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2197 Rotation = sitTargetOrient; 2323 Rotation = sitTargetOrient;
2198 ParentPosition = part.AbsolutePosition; 2324 ParentPosition = part.AbsolutePosition;
2325 part.ParentGroup.AddAvatar(UUID);
2199 } 2326 }
2200 else 2327 else
2201 { 2328 {
2202 m_pos -= part.AbsolutePosition; 2329 m_pos -= part.AbsolutePosition;
2203 ParentPosition = part.AbsolutePosition; 2330 ParentPosition = part.AbsolutePosition;
2331 part.ParentGroup.AddAvatar(UUID);
2204 2332
2205// m_log.DebugFormat( 2333// m_log.DebugFormat(
2206// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2334// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -2298,14 +2426,15 @@ namespace OpenSim.Region.Framework.Scenes
2298 direc.Z *= 2.6f; 2426 direc.Z *= 2.6f;
2299 2427
2300 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2428 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
2301 Animator.TrySetMovementAnimation("PREJUMP"); 2429// Animator.TrySetMovementAnimation("PREJUMP");
2302 Animator.TrySetMovementAnimation("JUMP"); 2430// Animator.TrySetMovementAnimation("JUMP");
2303 } 2431 }
2304 } 2432 }
2305 } 2433 }
2306 2434
2307 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2435 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2308 m_forceToApply = direc; 2436 m_forceToApply = direc;
2437 Animator.UpdateMovementAnimations();
2309 } 2438 }
2310 2439
2311 #endregion 2440 #endregion
@@ -3039,6 +3168,9 @@ namespace OpenSim.Region.Framework.Scenes
3039 cAgent.AlwaysRun = SetAlwaysRun; 3168 cAgent.AlwaysRun = SetAlwaysRun;
3040 3169
3041 cAgent.Appearance = new AvatarAppearance(Appearance); 3170 cAgent.Appearance = new AvatarAppearance(Appearance);
3171
3172 cAgent.ParentPart = ParentUUID;
3173 cAgent.SitOffset = m_pos;
3042 3174
3043 lock (scriptedcontrols) 3175 lock (scriptedcontrols)
3044 { 3176 {
@@ -3098,6 +3230,8 @@ namespace OpenSim.Region.Framework.Scenes
3098 CameraAtAxis = cAgent.AtAxis; 3230 CameraAtAxis = cAgent.AtAxis;
3099 CameraLeftAxis = cAgent.LeftAxis; 3231 CameraLeftAxis = cAgent.LeftAxis;
3100 CameraUpAxis = cAgent.UpAxis; 3232 CameraUpAxis = cAgent.UpAxis;
3233 ParentUUID = cAgent.ParentPart;
3234 m_prevSitOffset = cAgent.SitOffset;
3101 3235
3102 // When we get to the point of re-computing neighbors everytime this 3236 // When we get to the point of re-computing neighbors everytime this
3103 // changes, then start using the agent's drawdistance rather than the 3237 // changes, then start using the agent's drawdistance rather than the
@@ -3250,18 +3384,6 @@ namespace OpenSim.Region.Framework.Scenes
3250 if (IsChildAgent) 3384 if (IsChildAgent)
3251 return; 3385 return;
3252 3386
3253 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3254 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3255 // as of this comment the interval is set in AddToPhysicalScene
3256 if (Animator != null)
3257 {
3258// if (m_updateCount > 0)
3259// {
3260 Animator.UpdateMovementAnimations();
3261// m_updateCount--;
3262// }
3263 }
3264
3265 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3387 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3266 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3388 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3267 3389
@@ -3304,6 +3426,8 @@ namespace OpenSim.Region.Framework.Scenes
3304 } 3426 }
3305 } 3427 }
3306 3428
3429 RaiseCollisionScriptEvents(coldata);
3430
3307 if (Invulnerable) 3431 if (Invulnerable)
3308 return; 3432 return;
3309 3433
@@ -3888,6 +4012,12 @@ namespace OpenSim.Region.Framework.Scenes
3888 4012
3889 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 4013 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3890 { 4014 {
4015 string reason;
4016
4017 // Honor bans
4018 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
4019 return;
4020
3891 SceneObjectGroup telehub = null; 4021 SceneObjectGroup telehub = null;
3892 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 4022 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
3893 { 4023 {
@@ -3927,11 +4057,173 @@ namespace OpenSim.Region.Framework.Scenes
3927 pos = land.LandData.UserLocation; 4057 pos = land.LandData.UserLocation;
3928 } 4058 }
3929 } 4059 }
3930 4060
3931 land.SendLandUpdateToClient(ControllingClient); 4061 land.SendLandUpdateToClient(ControllingClient);
3932 } 4062 }
3933 } 4063 }
3934 4064
4065 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
4066 {
4067 lock(m_collisionEventLock)
4068 {
4069 if (m_collisionEventFlag)
4070 return;
4071 m_collisionEventFlag = true;
4072 }
4073
4074 Util.FireAndForget(delegate(object x)
4075 {
4076 try
4077 {
4078 List<uint> thisHitColliders = new List<uint>();
4079 List<uint> endedColliders = new List<uint>();
4080 List<uint> startedColliders = new List<uint>();
4081
4082 foreach (uint localid in coldata.Keys)
4083 {
4084 thisHitColliders.Add(localid);
4085 if (!m_lastColliders.Contains(localid))
4086 {
4087 startedColliders.Add(localid);
4088 }
4089 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
4090 }
4091
4092 // calculate things that ended colliding
4093 foreach (uint localID in m_lastColliders)
4094 {
4095 if (!thisHitColliders.Contains(localID))
4096 {
4097 endedColliders.Add(localID);
4098 }
4099 }
4100 //add the items that started colliding this time to the last colliders list.
4101 foreach (uint localID in startedColliders)
4102 {
4103 m_lastColliders.Add(localID);
4104 }
4105 // remove things that ended colliding from the last colliders list
4106 foreach (uint localID in endedColliders)
4107 {
4108 m_lastColliders.Remove(localID);
4109 }
4110
4111 // do event notification
4112 if (startedColliders.Count > 0)
4113 {
4114 ColliderArgs StartCollidingMessage = new ColliderArgs();
4115 List<DetectedObject> colliding = new List<DetectedObject>();
4116 foreach (uint localId in startedColliders)
4117 {
4118 if (localId == 0)
4119 continue;
4120
4121 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4122 string data = "";
4123 if (obj != null)
4124 {
4125 DetectedObject detobj = new DetectedObject();
4126 detobj.keyUUID = obj.UUID;
4127 detobj.nameStr = obj.Name;
4128 detobj.ownerUUID = obj.OwnerID;
4129 detobj.posVector = obj.AbsolutePosition;
4130 detobj.rotQuat = obj.GetWorldRotation();
4131 detobj.velVector = obj.Velocity;
4132 detobj.colliderType = 0;
4133 detobj.groupUUID = obj.GroupID;
4134 colliding.Add(detobj);
4135 }
4136 }
4137
4138 if (colliding.Count > 0)
4139 {
4140 StartCollidingMessage.Colliders = colliding;
4141
4142 foreach (SceneObjectGroup att in GetAttachments())
4143 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
4144 }
4145 }
4146
4147 if (endedColliders.Count > 0)
4148 {
4149 ColliderArgs EndCollidingMessage = new ColliderArgs();
4150 List<DetectedObject> colliding = new List<DetectedObject>();
4151 foreach (uint localId in endedColliders)
4152 {
4153 if (localId == 0)
4154 continue;
4155
4156 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4157 string data = "";
4158 if (obj != null)
4159 {
4160 DetectedObject detobj = new DetectedObject();
4161 detobj.keyUUID = obj.UUID;
4162 detobj.nameStr = obj.Name;
4163 detobj.ownerUUID = obj.OwnerID;
4164 detobj.posVector = obj.AbsolutePosition;
4165 detobj.rotQuat = obj.GetWorldRotation();
4166 detobj.velVector = obj.Velocity;
4167 detobj.colliderType = 0;
4168 detobj.groupUUID = obj.GroupID;
4169 colliding.Add(detobj);
4170 }
4171 }
4172
4173 if (colliding.Count > 0)
4174 {
4175 EndCollidingMessage.Colliders = colliding;
4176
4177 foreach (SceneObjectGroup att in GetAttachments())
4178 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4179 }
4180 }
4181
4182 if (thisHitColliders.Count > 0)
4183 {
4184 ColliderArgs CollidingMessage = new ColliderArgs();
4185 List<DetectedObject> colliding = new List<DetectedObject>();
4186 foreach (uint localId in thisHitColliders)
4187 {
4188 if (localId == 0)
4189 continue;
4190
4191 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4192 string data = "";
4193 if (obj != null)
4194 {
4195 DetectedObject detobj = new DetectedObject();
4196 detobj.keyUUID = obj.UUID;
4197 detobj.nameStr = obj.Name;
4198 detobj.ownerUUID = obj.OwnerID;
4199 detobj.posVector = obj.AbsolutePosition;
4200 detobj.rotQuat = obj.GetWorldRotation();
4201 detobj.velVector = obj.Velocity;
4202 detobj.colliderType = 0;
4203 detobj.groupUUID = obj.GroupID;
4204 colliding.Add(detobj);
4205 }
4206 }
4207
4208 if (colliding.Count > 0)
4209 {
4210 CollidingMessage.Colliders = colliding;
4211
4212 lock (m_attachments)
4213 {
4214 foreach (SceneObjectGroup att in m_attachments)
4215 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4216 }
4217 }
4218 }
4219 }
4220 finally
4221 {
4222 m_collisionEventFlag = false;
4223 }
4224 });
4225 }
4226
3935 private void TeleportFlagsDebug() { 4227 private void TeleportFlagsDebug() {
3936 4228
3937 // Some temporary debugging help to show all the TeleportFlags we have... 4229 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -3956,6 +4248,5 @@ namespace OpenSim.Region.Framework.Scenes
3956 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4248 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
3957 4249
3958 } 4250 }
3959
3960 } 4251 }
3961} 4252}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index e6b88a3..1cd8189 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -244,6 +244,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
244 sr.Close(); 244 sr.Close();
245 } 245 }
246 246
247 XmlNodeList keymotion = doc.GetElementsByTagName("KeyframeMotion");
248 if (keymotion.Count > 0)
249 sceneObject.RootPart.KeyframeMotion = KeyframeMotion.FromData(sceneObject, Convert.FromBase64String(keymotion[0].InnerText));
250 else
251 sceneObject.RootPart.KeyframeMotion = null;
252
247 // Script state may, or may not, exist. Not having any, is NOT 253 // Script state may, or may not, exist. Not having any, is NOT
248 // ever a problem. 254 // ever a problem.
249 sceneObject.LoadScriptState(doc); 255 sceneObject.LoadScriptState(doc);
@@ -347,6 +353,21 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
347 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 353 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
348 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 354 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
349 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 355 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
356
357 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
358 m_SOPXmlProcessors.Add("Force", ProcessForce);
359 m_SOPXmlProcessors.Add("Torque", ProcessTorque);
360 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
361
362
363 m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle);
364
365 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType);
366 m_SOPXmlProcessors.Add("Density", ProcessDensity);
367 m_SOPXmlProcessors.Add("Friction", ProcessFriction);
368 m_SOPXmlProcessors.Add("Bounce", ProcessBounce);
369 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier);
370
350 #endregion 371 #endregion
351 372
352 #region TaskInventoryXmlProcessors initialization 373 #region TaskInventoryXmlProcessors initialization
@@ -374,7 +395,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
374 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask); 395 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask);
375 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType); 396 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType);
376 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged); 397 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged);
377 398
378 #endregion 399 #endregion
379 400
380 #region ShapeXmlProcessors initialization 401 #region ShapeXmlProcessors initialization
@@ -569,6 +590,49 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
569 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty); 590 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty);
570 } 591 }
571 592
593 private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlTextReader reader)
594 {
595 obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty);
596 }
597
598 private static void ProcessDensity(SceneObjectPart obj, XmlTextReader reader)
599 {
600 obj.Density = reader.ReadElementContentAsFloat("Density", String.Empty);
601 }
602
603 private static void ProcessFriction(SceneObjectPart obj, XmlTextReader reader)
604 {
605 obj.Friction = reader.ReadElementContentAsFloat("Friction", String.Empty);
606 }
607
608 private static void ProcessBounce(SceneObjectPart obj, XmlTextReader reader)
609 {
610 obj.Bounciness = reader.ReadElementContentAsFloat("Bounce", String.Empty);
611 }
612
613 private static void ProcessGravityModifier(SceneObjectPart obj, XmlTextReader reader)
614 {
615 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty);
616 }
617
618 private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader)
619 {
620 bool errors = false;
621 SOPVehicle _vehicle = new SOPVehicle();
622
623 _vehicle.FromXml2(reader, out errors);
624
625 if (errors)
626 {
627 obj.sopVehicle = null;
628 m_log.DebugFormat(
629 "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.",
630 obj.Name, obj.UUID);
631 }
632 else
633 obj.sopVehicle = _vehicle;
634 }
635
572 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) 636 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader)
573 { 637 {
574 List<string> errorNodeNames; 638 List<string> errorNodeNames;
@@ -733,6 +797,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
733 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 797 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
734 } 798 }
735 799
800 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
801 {
802 obj.Buoyancy = (float)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
803 }
804
805 private static void ProcessForce(SceneObjectPart obj, XmlTextReader reader)
806 {
807 obj.Force = Util.ReadVector(reader, "Force");
808 }
809 private static void ProcessTorque(SceneObjectPart obj, XmlTextReader reader)
810 {
811 obj.Torque = Util.ReadVector(reader, "Torque");
812 }
813
814 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
815 {
816 obj.VolumeDetectActive = Util.ReadBoolean(reader);
817 }
818
736 #endregion 819 #endregion
737 820
738 #region TaskInventoryXmlProcessors 821 #region TaskInventoryXmlProcessors
@@ -1120,6 +1203,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1120 }); 1203 });
1121 1204
1122 writer.WriteEndElement(); 1205 writer.WriteEndElement();
1206
1207 if (sog.RootPart.KeyframeMotion != null)
1208 {
1209 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1210
1211 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1212 writer.WriteBase64(data, 0, data.Length);
1213 writer.WriteEndElement();
1214 }
1215
1123 writer.WriteEndElement(); 1216 writer.WriteEndElement();
1124 } 1217 }
1125 1218
@@ -1218,6 +1311,27 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1218 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1311 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1219 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1312 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1220 1313
1314 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1315
1316 WriteVector(writer, "Force", sop.Force);
1317 WriteVector(writer, "Torque", sop.Torque);
1318
1319 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1320
1321 if (sop.sopVehicle != null)
1322 sop.sopVehicle.ToXml2(writer);
1323
1324 if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType())
1325 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
1326 if (sop.Density != 1000.0f)
1327 writer.WriteElementString("Density", sop.Density.ToString().ToLower());
1328 if (sop.Friction != 0.6f)
1329 writer.WriteElementString("Friction", sop.Friction.ToString().ToLower());
1330 if (sop.Bounciness != 0.5f)
1331 writer.WriteElementString("Bounce", sop.Bounciness.ToString().ToLower());
1332 if (sop.GravityModifier != 1.0f)
1333 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
1334
1221 writer.WriteEndElement(); 1335 writer.WriteEndElement();
1222 } 1336 }
1223 1337
@@ -1487,12 +1601,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1487 { 1601 {
1488 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1602 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1489 1603
1490 if (reader.IsEmptyElement)
1491 {
1492 reader.Read();
1493 return tinv;
1494 }
1495
1496 reader.ReadStartElement(name, String.Empty); 1604 reader.ReadStartElement(name, String.Empty);
1497 1605
1498 while (reader.Name == "TaskInventoryItem") 1606 while (reader.Name == "TaskInventoryItem")
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..7bbf1bd 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -27,202 +27,307 @@
27 27
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic;
30using log4net; 31using log4net;
31using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
33 35
34namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
35{ 37{
36 public class UndoState 38 public class UndoState
37 { 39 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40 const int UNDOEXPIRESECONDS = 300; // undo expire time (nice to have it came from a ini later)
39
40 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero;
42 public Quaternion Rotation = Quaternion.Identity;
43
44 /// <summary>
45 /// Is this undo state for an entire group?
46 /// </summary>
47 public bool ForGroup;
48 41
42 public ObjectChangeData data;
43 public DateTime creationtime;
49 /// <summary> 44 /// <summary>
50 /// Constructor. 45 /// Constructor.
51 /// </summary> 46 /// </summary>
52 /// <param name="part"></param> 47 /// <param name="part"></param>
53 /// <param name="forGroup">True if the undo is for an entire group</param> 48 /// <param name="change">bit field with what is changed</param>
54 public UndoState(SceneObjectPart part, bool forGroup) 49 ///
50 public UndoState(SceneObjectPart part, ObjectChangeType change)
55 { 51 {
56 if (part.ParentID == 0) 52 data = new ObjectChangeData();
57 { 53 data.change = change;
58 ForGroup = forGroup; 54 creationtime = DateTime.UtcNow;
59
60// if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition;
62// else
63// Position = part.OffsetPosition;
64
65// m_log.DebugFormat(
66// "[UNDO STATE]: Storing undo position {0} for root part", Position);
67 55
68 Rotation = part.RotationOffset; 56 if (part.ParentGroup.RootPart == part)
69 57 {
70// m_log.DebugFormat( 58 if ((change & ObjectChangeType.Position) != 0)
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); 59 data.position = part.ParentGroup.AbsolutePosition;
72 60 if ((change & ObjectChangeType.Rotation) != 0)
73 Scale = part.Shape.Scale; 61 data.rotation = part.RotationOffset;
74 62 if ((change & ObjectChangeType.Scale) != 0)
75// m_log.DebugFormat( 63 data.scale = part.Shape.Scale;
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 64 }
78 else 65 else
79 { 66 {
80 Position = part.OffsetPosition; 67 if ((change & ObjectChangeType.Position) != 0)
81// m_log.DebugFormat( 68 data.position = part.OffsetPosition;
82// "[UNDO STATE]: Storing undo position {0} for child part", Position); 69 if ((change & ObjectChangeType.Rotation) != 0)
70 data.rotation = part.RotationOffset;
71 if ((change & ObjectChangeType.Scale) != 0)
72 data.scale = part.Shape.Scale;
73 }
74 }
75 /// <summary>
76 /// check if undo or redo is too old
77 /// </summary>
83 78
84 Rotation = part.RotationOffset; 79 public bool checkExpire()
85// m_log.DebugFormat( 80 {
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); 81 TimeSpan t = DateTime.UtcNow - creationtime;
82 if (t.Seconds > UNDOEXPIRESECONDS)
83 return true;
84 return false;
85 }
87 86
88 Scale = part.Shape.Scale; 87 /// <summary>
89// m_log.DebugFormat( 88 /// updates undo or redo creation time to now
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 89 /// </summary>
91 } 90 public void updateExpire()
91 {
92 creationtime = DateTime.UtcNow;
92 } 93 }
93 94
94 /// <summary> 95 /// <summary>
95 /// Compare the relevant state in the given part to this state. 96 /// Compare the relevant state in the given part to this state.
96 /// </summary> 97 /// </summary>
97 /// <param name="part"></param> 98 /// <param name="part"></param>
98 /// <returns>true if both the part's position, rotation and scale match those in this undo state. False otherwise.</returns> 99 /// <returns>true what fiels and related data are equal, False otherwise.</returns>
99 public bool Compare(SceneObjectPart part) 100 ///
101 public bool Compare(SceneObjectPart part, ObjectChangeType change)
100 { 102 {
103 if (data.change != change) // if diferent targets, then they are diferent
104 return false;
105
101 if (part != null) 106 if (part != null)
102 { 107 {
103 if (part.ParentID == 0) 108 if (part.ParentID == 0)
104 return 109 {
105 Position == part.ParentGroup.AbsolutePosition 110 if ((change & ObjectChangeType.Position) != 0 && data.position != part.ParentGroup.AbsolutePosition)
106 && Rotation == part.RotationOffset 111 return false;
107 && Scale == part.Shape.Scale; 112 }
108 else 113 else
109 return 114 {
110 Position == part.OffsetPosition 115 if ((change & ObjectChangeType.Position) != 0 && data.position != part.OffsetPosition)
111 && Rotation == part.RotationOffset 116 return false;
112 && Scale == part.Shape.Scale; 117 }
113 } 118
119 if ((change & ObjectChangeType.Rotation) != 0 && data.rotation != part.RotationOffset)
120 return false;
121 if ((change & ObjectChangeType.Rotation) != 0 && data.scale == part.Shape.Scale)
122 return false;
123 return true;
114 124
125 }
115 return false; 126 return false;
116 } 127 }
117 128
118 public void PlaybackState(SceneObjectPart part) 129 /// <summary>
130 /// executes the undo or redo to a part or its group
131 /// </summary>
132 /// <param name="part"></param>
133 ///
134
135 public void PlayState(SceneObjectPart part)
119 { 136 {
120 part.Undoing = true; 137 part.Undoing = true;
121 138
122 if (part.ParentID == 0) 139 SceneObjectGroup grp = part.ParentGroup;
123 {
124// m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId);
127 140
128 if (Position != Vector3.Zero) 141 if (grp != null)
129 { 142 {
130 if (ForGroup) 143 grp.doChangeObject(part, data);
131 part.ParentGroup.AbsolutePosition = Position; 144 }
132 else 145 part.Undoing = false;
133 part.ParentGroup.UpdateRootPosition(Position); 146 }
134 } 147 }
135 148
136// m_log.DebugFormat( 149 public class UndoRedoState
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", 150 {
138// part.RotationOffset, Rotation, part.Name, part.LocalId); 151 int size;
152 public LinkedList<UndoState> m_redo = new LinkedList<UndoState>();
153 public LinkedList<UndoState> m_undo = new LinkedList<UndoState>();
139 154
140 if (ForGroup) 155 /// <summary>
141 part.UpdateRotation(Rotation); 156 /// creates a new UndoRedoState with default states memory size
142 else 157 /// </summary>
143 part.ParentGroup.UpdateRootRotation(Rotation);
144 158
145 if (Scale != Vector3.Zero) 159 public UndoRedoState()
146 { 160 {
147// m_log.DebugFormat( 161 size = 5;
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", 162 }
149// part.Shape.Scale, Scale, part.Name, part.LocalId);
150 163
151 if (ForGroup) 164 /// <summary>
152 part.ParentGroup.GroupResize(Scale); 165 /// creates a new UndoRedoState with states memory having indicated size
153 else 166 /// </summary>
154 part.Resize(Scale); 167 /// <param name="size"></param>
155 }
156 168
157 part.ParentGroup.ScheduleGroupForTerseUpdate(); 169 public UndoRedoState(int _size)
158 } 170 {
171 if (_size < 3)
172 size = 3;
159 else 173 else
160 { 174 size = _size;
161 // Note: Updating these properties on sop automatically schedules an update if needed 175 }
162 if (Position != Vector3.Zero)
163 {
164// m_log.DebugFormat(
165// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
166// part.OffsetPosition, Position, part.Name, part.LocalId);
167 176
168 part.OffsetPosition = Position; 177 /// <summary>
169 } 178 /// returns number of undo entries in memory
179 /// </summary>
170 180
171// m_log.DebugFormat( 181 public int Count
172// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", 182 {
173// part.RotationOffset, Rotation, part.Name, part.LocalId); 183 get { return m_undo.Count; }
184 }
174 185
175 part.UpdateRotation(Rotation); 186 /// <summary>
187 /// clears all undo and redo entries
188 /// </summary>
176 189
177 if (Scale != Vector3.Zero) 190 public void Clear()
191 {
192 m_undo.Clear();
193 m_redo.Clear();
194 }
195
196 /// <summary>
197 /// adds a new state undo to part or its group, with changes indicated by what bits
198 /// </summary>
199 /// <param name="part"></param>
200 /// <param name="change">bit field with what is changed</param>
201
202 public void StoreUndo(SceneObjectPart part, ObjectChangeType change)
203 {
204 lock (m_undo)
205 {
206 UndoState last;
207
208 if (m_redo.Count > 0) // last code seems to clear redo on every new undo
178 { 209 {
179// m_log.DebugFormat( 210 m_redo.Clear();
180// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", 211 }
181// part.Shape.Scale, Scale, part.Name, part.LocalId);
182 212
183 part.Resize(Scale); 213 if (m_undo.Count > 0)
214 {
215 // check expired entry
216 last = m_undo.First.Value;
217 if (last != null && last.checkExpire())
218 m_undo.Clear();
219 else
220 {
221 // see if we actually have a change
222 if (last != null)
223 {
224 if (last.Compare(part, change))
225 return;
226 }
227 }
184 } 228 }
185 }
186 229
187 part.Undoing = false; 230 // limite size
231 while (m_undo.Count >= size)
232 m_undo.RemoveLast();
233
234 UndoState nUndo = new UndoState(part, change);
235 m_undo.AddFirst(nUndo);
236 }
188 } 237 }
189 238
190 public void PlayfwdState(SceneObjectPart part) 239 /// <summary>
191 { 240 /// executes last state undo to part or its group
192 part.Undoing = true; 241 /// current state is pushed into redo
242 /// </summary>
243 /// <param name="part"></param>
193 244
194 if (part.ParentID == 0) 245 public void Undo(SceneObjectPart part)
246 {
247 lock (m_undo)
195 { 248 {
196 if (Position != Vector3.Zero) 249 UndoState nUndo;
197 part.ParentGroup.AbsolutePosition = Position;
198
199 if (Rotation != Quaternion.Identity)
200 part.UpdateRotation(Rotation);
201 250
202 if (Scale != Vector3.Zero) 251 // expire redo
252 if (m_redo.Count > 0)
203 { 253 {
204 if (ForGroup) 254 nUndo = m_redo.First.Value;
205 part.ParentGroup.GroupResize(Scale); 255 if (nUndo != null && nUndo.checkExpire())
206 else 256 m_redo.Clear();
207 part.Resize(Scale);
208 } 257 }
209 258
210 part.ParentGroup.ScheduleGroupForTerseUpdate(); 259 if (m_undo.Count > 0)
260 {
261 UndoState goback = m_undo.First.Value;
262 // check expired
263 if (goback != null && goback.checkExpire())
264 {
265 m_undo.Clear();
266 return;
267 }
268
269 if (goback != null)
270 {
271 m_undo.RemoveFirst();
272
273 // redo limite size
274 while (m_redo.Count >= size)
275 m_redo.RemoveLast();
276
277 nUndo = new UndoState(part, goback.data.change); // new value in part should it be full goback copy?
278 m_redo.AddFirst(nUndo);
279
280 goback.PlayState(part);
281 }
282 }
211 } 283 }
212 else 284 }
285
286 /// <summary>
287 /// executes last state redo to part or its group
288 /// current state is pushed into undo
289 /// </summary>
290 /// <param name="part"></param>
291
292 public void Redo(SceneObjectPart part)
293 {
294 lock (m_undo)
213 { 295 {
214 // Note: Updating these properties on sop automatically schedules an update if needed 296 UndoState nUndo;
215 if (Position != Vector3.Zero)
216 part.OffsetPosition = Position;
217 297
218 if (Rotation != Quaternion.Identity) 298 // expire undo
219 part.UpdateRotation(Rotation); 299 if (m_undo.Count > 0)
300 {
301 nUndo = m_undo.First.Value;
302 if (nUndo != null && nUndo.checkExpire())
303 m_undo.Clear();
304 }
220 305
221 if (Scale != Vector3.Zero) 306 if (m_redo.Count > 0)
222 part.Resize(Scale); 307 {
308 UndoState gofwd = m_redo.First.Value;
309 // check expired
310 if (gofwd != null && gofwd.checkExpire())
311 {
312 m_redo.Clear();
313 return;
314 }
315
316 if (gofwd != null)
317 {
318 m_redo.RemoveFirst();
319
320 // limite undo size
321 while (m_undo.Count >= size)
322 m_undo.RemoveLast();
323
324 nUndo = new UndoState(part, gofwd.data.change); // new value in part should it be full gofwd copy?
325 m_undo.AddFirst(nUndo);
326
327 gofwd.PlayState(part);
328 }
329 }
223 } 330 }
224
225 part.Undoing = false;
226 } 331 }
227 } 332 }
228 333
@@ -247,4 +352,4 @@ namespace OpenSim.Region.Framework.Scenes
247 m_terrainModule.UndoTerrain(m_terrainChannel); 352 m_terrainModule.UndoTerrain(m_terrainChannel);
248 } 353 }
249 } 354 }
250} \ No newline at end of file 355}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index efb68a2..411e421 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -87,10 +87,6 @@ namespace OpenSim.Region.Framework.Scenes
87 /// <param name="assetUuids">The assets gathered</param> 87 /// <param name="assetUuids">The assets gathered</param>
88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
89 { 89 {
90 // avoid infinite loops
91 if (assetUuids.ContainsKey(assetUuid))
92 return;
93
94 try 90 try
95 { 91 {
96 assetUuids[assetUuid] = assetType; 92 assetUuids[assetUuid] = assetType;