aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs11
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs13
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-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/SOPVehicle.cs742
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs328
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs9
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs679
-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.cs238
-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.cs901
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs484
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs804
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs377
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs80
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs146
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
28 files changed, 4323 insertions, 1052 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index eb07165..69ce967 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -75,6 +76,10 @@ namespace OpenSim.Region.Framework.Interfaces
75 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> 76 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
76 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); 77 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
77 78
79 // Same as above, but also load script states from a separate doc
80 ISceneEntity RezSingleAttachmentFromInventory(
81 IScenePresence presence, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
82
78 /// <summary> 83 /// <summary>
79 /// Rez multiple attachments from a user's inventory 84 /// Rez multiple attachments from a user's inventory
80 /// </summary> 85 /// </summary>
@@ -96,7 +101,6 @@ namespace OpenSim.Region.Framework.Interfaces
96 /// <param name="itemID"></param> 101 /// <param name="itemID"></param>
97 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID); 102 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID);
98 103
99 /// <summary>
100 /// Update the position of an attachment. 104 /// Update the position of an attachment.
101 /// </summary> 105 /// </summary>
102 /// <param name="sog"></param> 106 /// <param name="sog"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 15060fd..4b17b9a 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -115,6 +115,8 @@ namespace OpenSim.Region.Framework.Interfaces
115 /// <param name="stateSource"></param> 115 /// <param name="stateSource"></param>
116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
117 117
118 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
119
118 /// <summary> 120 /// <summary>
119 /// Stop a script which is in this prim's inventory. 121 /// Stop a script which is in this prim's inventory.
120 /// </summary> 122 /// </summary>
@@ -229,5 +231,6 @@ namespace OpenSim.Region.Framework.Interfaces
229 /// A <see cref="Dictionary`2"/> 231 /// A <see cref="Dictionary`2"/>
230 /// </returns> 232 /// </returns>
231 Dictionary<UUID, string> GetScriptStates(); 233 Dictionary<UUID, string> GetScriptStates();
234 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
232 } 235 }
233} 236}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 07e97d5..76f1641 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -35,16 +35,18 @@ using OpenSim.Region.Framework.Scenes;
35 35
36namespace OpenSim.Region.Framework.Interfaces 36namespace OpenSim.Region.Framework.Interfaces
37{ 37{
38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version);
39
38 public interface IEntityTransferModule 40 public interface IEntityTransferModule
39 { 41 {
40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, 42 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position,
41 Vector3 lookAt, uint teleportFlags); 43 Vector3 lookAt, uint teleportFlags);
42 44
45 bool TeleportHome(UUID id, IClientAPI client);
46
43 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 47 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
44 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); 48 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq);
45 49
46 void TeleportHome(UUID id, IClientAPI client);
47
48 bool Cross(ScenePresence agent, bool isFlying); 50 bool Cross(ScenePresence agent, bool isFlying);
49 51
50 void AgentArrivedAtDestination(UUID agent); 52 void AgentArrivedAtDestination(UUID agent);
@@ -53,7 +55,12 @@ namespace OpenSim.Region.Framework.Interfaces
53 55
54 void EnableChildAgent(ScenePresence agent, GridRegion region); 56 void EnableChildAgent(ScenePresence agent, GridRegion region);
55 57
58 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos);
59
56 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 60 void Cross(SceneObjectGroup sog, Vector3 position, bool silent);
61
62 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version);
63
57 } 64 }
58 65
59 public interface IUserAgentVerificationModule 66 public interface IUserAgentVerificationModule
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 721f0ee..72e79ed 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -45,5 +45,7 @@ namespace OpenSim.Region.Framework.Interfaces
45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.). 45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.).
46 /// </summary> 46 /// </summary>
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange();
49 void TriggerRegionInfoChange();
48 } 50 }
49} 51}
diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
index 2d6287f..67a500f 100644
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
@@ -68,6 +68,14 @@ namespace OpenSim.Region.Framework.Interfaces
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); 68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69 69
70 /// <summary> 70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
71 /// Close agent. 79 /// Close agent.
72 /// </summary> 80 /// </summary>
73 /// <param name="regionHandle"></param> 81 /// <param name="regionHandle"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index 18c45dd..2d6758b 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -68,6 +68,8 @@ namespace OpenSim.Region.Framework.Interfaces
68 68
69 ArrayList GetScriptErrors(UUID itemID); 69 ArrayList GetScriptErrors(UUID itemID);
70 70
71 bool HasScript(UUID itemID, out bool running);
72
71 void SaveAllState(); 73 void SaveAllState();
72 74
73 /// <summary> 75 /// <summary>
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..e01f649
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,27 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster LImited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6// Mod 2
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface ISnmpModule
11{
12 void Trap(int code, string Message, Scene scene);
13 void Critical(string Message, Scene scene);
14 void Warning(string Message, Scene scene);
15 void Major(string Message, Scene scene);
16 void ColdStart(int step , Scene scene);
17 void Shutdown(int step , Scene scene);
18 //
19 // Node Start/stop events
20 //
21 void LinkUp(Scene scene);
22 void LinkDown(Scene scene);
23 void BootInfo(string data, Scene scene);
24 void trapDebug(string Module,string data, Scene scene);
25 void trapXMRE(int data, string Message, Scene scene);
26
27}
diff --git a/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
new file mode 100644
index 0000000..d1a4d8e
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -0,0 +1,13 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster Limited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6//
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface IUserAccountCacheModule
11{
12 void Remove(string name);
13}
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 14ecd44..32ee674 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -227,7 +227,8 @@ namespace OpenSim.Region.Framework
227 pluginAssembly.FullName, e.Message, e.StackTrace); 227 pluginAssembly.FullName, e.Message, e.StackTrace);
228 228
229 // justincc: Right now this is fatal to really get the user's attention 229 // justincc: Right now this is fatal to really get the user's attention
230 throw e; 230 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
231 //throw e;
231 } 232 }
232 } 233 }
233 234
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 6ff2a6f..605ee32 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;
@@ -867,6 +871,26 @@ namespace OpenSim.Region.Framework.Scenes
867 } 871 }
868 } 872 }
869 } 873 }
874 public void TriggerTerrainUpdate()
875 {
876 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
877 if (handlerTerrainUpdate != null)
878 {
879 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
880 {
881 try
882 {
883 d();
884 }
885 catch (Exception e)
886 {
887 m_log.ErrorFormat(
888 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
889 e.Message, e.StackTrace);
890 }
891 }
892 }
893 }
870 894
871 public void TriggerTerrainTick() 895 public void TriggerTerrainTick()
872 { 896 {
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/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 6ae4adc..d1739de 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -117,34 +117,22 @@ namespace OpenSim.Region.Framework.Scenes
117 /// <param name="item"></param> 117 /// <param name="item"></param>
118 public bool AddInventoryItem(InventoryItemBase item) 118 public bool AddInventoryItem(InventoryItemBase item)
119 { 119 {
120 if (UUID.Zero == item.Folder) 120 InventoryFolderBase folder;
121
122 if (item.Folder == UUID.Zero)
121 { 123 {
122 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 124 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
123 if (f != null) 125 if (folder == null)
124 { 126 {
125// m_log.DebugFormat( 127 folder = InventoryService.GetRootFolder(item.Owner);
126// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", 128
127// f.Name, (AssetType)f.Type, item.Name); 129 if (folder == null)
128
129 item.Folder = f.ID;
130 }
131 else
132 {
133 f = InventoryService.GetRootFolder(item.Owner);
134 if (f != null)
135 {
136 item.Folder = f.ID;
137 }
138 else
139 {
140 m_log.WarnFormat(
141 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
142 item.Owner, item.Name);
143 return false; 130 return false;
144 }
145 } 131 }
132
133 item.Folder = folder.ID;
146 } 134 }
147 135
148 if (InventoryService.AddItem(item)) 136 if (InventoryService.AddItem(item))
149 { 137 {
150 int userlevel = 0; 138 int userlevel = 0;
@@ -264,8 +252,7 @@ namespace OpenSim.Region.Framework.Scenes
264 252
265 // Update item with new asset 253 // Update item with new asset
266 item.AssetID = asset.FullID; 254 item.AssetID = asset.FullID;
267 if (group.UpdateInventoryItem(item)) 255 group.UpdateInventoryItem(item);
268 remoteClient.SendAgentAlertMessage("Script saved", false);
269 256
270 part.SendPropertiesToClient(remoteClient); 257 part.SendPropertiesToClient(remoteClient);
271 258
@@ -276,12 +263,7 @@ namespace OpenSim.Region.Framework.Scenes
276 { 263 {
277 // Needs to determine which engine was running it and use that 264 // Needs to determine which engine was running it and use that
278 // 265 //
279 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 266 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
280 errors = part.Inventory.GetScriptErrors(item.ItemID);
281 }
282 else
283 {
284 remoteClient.SendAgentAlertMessage("Script saved", false);
285 } 267 }
286 268
287 // Tell anyone managing scripts that a script has been reloaded/changed 269 // Tell anyone managing scripts that a script has been reloaded/changed
@@ -349,6 +331,7 @@ namespace OpenSim.Region.Framework.Scenes
349 331
350 if (UUID.Zero == transactionID) 332 if (UUID.Zero == transactionID)
351 { 333 {
334 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
352 item.Name = itemUpd.Name; 335 item.Name = itemUpd.Name;
353 item.Description = itemUpd.Description; 336 item.Description = itemUpd.Description;
354 337
@@ -736,6 +719,8 @@ namespace OpenSim.Region.Framework.Scenes
736 return; 719 return;
737 } 720 }
738 721
722 if (newName == null) newName = item.Name;
723
739 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 724 AssetBase asset = AssetService.Get(item.AssetID.ToString());
740 725
741 if (asset != null) 726 if (asset != null)
@@ -792,6 +777,24 @@ namespace OpenSim.Region.Framework.Scenes
792 } 777 }
793 778
794 /// <summary> 779 /// <summary>
780 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
781 /// </summary>
782 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
783 {
784 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
785 foreach (InventoryItemBase b in items)
786 {
787 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
788 InventoryItemBase n = InventoryService.GetItem(b);
789 n.Folder = destfolder;
790 moveitems.Add(n);
791 remoteClient.SendInventoryItemCreateUpdate(n, 0);
792 }
793
794 MoveInventoryItem(remoteClient, moveitems);
795 }
796
797 /// <summary>
795 /// Move an item within the agent's inventory. 798 /// Move an item within the agent's inventory.
796 /// </summary> 799 /// </summary>
797 /// <param name="remoteClient"></param> 800 /// <param name="remoteClient"></param>
@@ -1134,6 +1137,10 @@ namespace OpenSim.Region.Framework.Scenes
1134 { 1137 {
1135 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1138 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1136 1139
1140 // Can't move a null item
1141 if (itemId == UUID.Zero)
1142 return;
1143
1137 if (null == part) 1144 if (null == part)
1138 { 1145 {
1139 m_log.WarnFormat( 1146 m_log.WarnFormat(
@@ -1243,6 +1250,10 @@ namespace OpenSim.Region.Framework.Scenes
1243 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1250 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1244 return; 1251 return;
1245 1252
1253 bool overrideNoMod = false;
1254 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1255 overrideNoMod = true;
1256
1246 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1257 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1247 { 1258 {
1248 // object cannot copy items to an object owned by a different owner 1259 // object cannot copy items to an object owned by a different owner
@@ -1252,7 +1263,7 @@ namespace OpenSim.Region.Framework.Scenes
1252 } 1263 }
1253 1264
1254 // must have both move and modify permission to put an item in an object 1265 // must have both move and modify permission to put an item in an object
1255 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1266 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1256 { 1267 {
1257 return; 1268 return;
1258 } 1269 }
@@ -1311,6 +1322,14 @@ namespace OpenSim.Region.Framework.Scenes
1311 1322
1312 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1323 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1313 { 1324 {
1325 SceneObjectPart destPart = GetSceneObjectPart(destID);
1326 if (destPart != null) // Move into a prim
1327 {
1328 foreach(UUID itemID in items)
1329 MoveTaskInventoryItem(destID, host, itemID);
1330 return destID; // Prim folder ID == prim ID
1331 }
1332
1314 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1333 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1315 1334
1316 UUID newFolderID = UUID.Random(); 1335 UUID newFolderID = UUID.Random();
@@ -1496,12 +1515,12 @@ namespace OpenSim.Region.Framework.Scenes
1496 agentTransactions.HandleTaskItemUpdateFromTransaction( 1515 agentTransactions.HandleTaskItemUpdateFromTransaction(
1497 remoteClient, part, transactionID, currentItem); 1516 remoteClient, part, transactionID, currentItem);
1498 1517
1499 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1518// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1500 remoteClient.SendAgentAlertMessage("Notecard saved", false); 1519// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1501 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1520// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1502 remoteClient.SendAgentAlertMessage("Script saved", false); 1521// remoteClient.SendAgentAlertMessage("Script saved", false);
1503 else 1522// else
1504 remoteClient.SendAgentAlertMessage("Item saved", false); 1523// remoteClient.SendAgentAlertMessage("Item saved", false);
1505 } 1524 }
1506 } 1525 }
1507 1526
@@ -1685,7 +1704,7 @@ namespace OpenSim.Region.Framework.Scenes
1685 } 1704 }
1686 1705
1687 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1706 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1688 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1707 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1689 agentID); 1708 agentID);
1690 AssetService.Store(asset); 1709 AssetService.Store(asset);
1691 1710
@@ -1841,23 +1860,32 @@ namespace OpenSim.Region.Framework.Scenes
1841 // build a list of eligible objects 1860 // build a list of eligible objects
1842 List<uint> deleteIDs = new List<uint>(); 1861 List<uint> deleteIDs = new List<uint>();
1843 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1862 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1844 1863 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1845 // Start with true for both, then remove the flags if objects
1846 // that we can't derez are part of the selection
1847 bool permissionToTake = true;
1848 bool permissionToTakeCopy = true;
1849 bool permissionToDelete = true;
1850 1864
1851 foreach (uint localID in localIDs) 1865 foreach (uint localID in localIDs)
1852 { 1866 {
1867 // Start with true for both, then remove the flags if objects
1868 // that we can't derez are part of the selection
1869 bool permissionToTake = true;
1870 bool permissionToTakeCopy = true;
1871 bool permissionToDelete = true;
1872
1853 // Invalid id 1873 // Invalid id
1854 SceneObjectPart part = GetSceneObjectPart(localID); 1874 SceneObjectPart part = GetSceneObjectPart(localID);
1855 if (part == null) 1875 if (part == null)
1876 {
1877 //Client still thinks the object exists, kill it
1878 deleteIDs.Add(localID);
1856 continue; 1879 continue;
1880 }
1857 1881
1858 // Already deleted by someone else 1882 // Already deleted by someone else
1859 if (part.ParentGroup.IsDeleted) 1883 if (part.ParentGroup.IsDeleted)
1884 {
1885 //Client still thinks the object exists, kill it
1886 deleteIDs.Add(localID);
1860 continue; 1887 continue;
1888 }
1861 1889
1862 // Can't delete child prims 1890 // Can't delete child prims
1863 if (part != part.ParentGroup.RootPart) 1891 if (part != part.ParentGroup.RootPart)
@@ -1865,9 +1893,6 @@ namespace OpenSim.Region.Framework.Scenes
1865 1893
1866 SceneObjectGroup grp = part.ParentGroup; 1894 SceneObjectGroup grp = part.ParentGroup;
1867 1895
1868 deleteIDs.Add(localID);
1869 deleteGroups.Add(grp);
1870
1871 if (remoteClient == null) 1896 if (remoteClient == null)
1872 { 1897 {
1873 // Autoreturn has a null client. Nothing else does. So 1898 // Autoreturn has a null client. Nothing else does. So
@@ -1884,83 +1909,195 @@ namespace OpenSim.Region.Framework.Scenes
1884 } 1909 }
1885 else 1910 else
1886 { 1911 {
1887 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1912 if (action == DeRezAction.TakeCopy)
1913 {
1914 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1915 permissionToTakeCopy = false;
1916 }
1917 else
1918 {
1888 permissionToTakeCopy = false; 1919 permissionToTakeCopy = false;
1889 1920 }
1890 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1921 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1891 permissionToTake = false; 1922 permissionToTake = false;
1892 1923
1893 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1924 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1894 permissionToDelete = false; 1925 permissionToDelete = false;
1895 } 1926 }
1896 }
1897 1927
1898 // Handle god perms 1928 // Handle god perms
1899 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1929 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1900 { 1930 {
1901 permissionToTake = true; 1931 permissionToTake = true;
1902 permissionToTakeCopy = true; 1932 permissionToTakeCopy = true;
1903 permissionToDelete = true; 1933 permissionToDelete = true;
1904 } 1934 }
1905 1935
1906 // If we're re-saving, we don't even want to delete 1936 // If we're re-saving, we don't even want to delete
1907 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1937 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1908 permissionToDelete = false; 1938 permissionToDelete = false;
1909 1939
1910 // if we want to take a copy, we also don't want to delete 1940 // if we want to take a copy, we also don't want to delete
1911 // Note: after this point, the permissionToTakeCopy flag 1941 // Note: after this point, the permissionToTakeCopy flag
1912 // becomes irrelevant. It already includes the permissionToTake 1942 // becomes irrelevant. It already includes the permissionToTake
1913 // permission and after excluding no copy items here, we can 1943 // permission and after excluding no copy items here, we can
1914 // just use that. 1944 // just use that.
1915 if (action == DeRezAction.TakeCopy) 1945 if (action == DeRezAction.TakeCopy)
1916 { 1946 {
1917 // If we don't have permission, stop right here 1947 // If we don't have permission, stop right here
1918 if (!permissionToTakeCopy) 1948 if (!permissionToTakeCopy)
1919 return; 1949 return;
1920 1950
1921 permissionToTake = true; 1951 permissionToTake = true;
1922 // Don't delete 1952 // Don't delete
1923 permissionToDelete = false; 1953 permissionToDelete = false;
1924 } 1954 }
1925 1955
1926 if (action == DeRezAction.Return) 1956 if (action == DeRezAction.Return)
1927 {
1928 if (remoteClient != null)
1929 { 1957 {
1930 if (Permissions.CanReturnObjects( 1958 if (remoteClient != null)
1931 null,
1932 remoteClient.AgentId,
1933 deleteGroups))
1934 { 1959 {
1935 permissionToTake = true; 1960 if (Permissions.CanReturnObjects(
1936 permissionToDelete = true; 1961 null,
1937 1962 remoteClient.AgentId,
1938 foreach (SceneObjectGroup g in deleteGroups) 1963 deleteGroups))
1939 { 1964 {
1940 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1965 permissionToTake = true;
1966 permissionToDelete = true;
1967
1968 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1941 } 1969 }
1942 } 1970 }
1971 else // Auto return passes through here with null agent
1972 {
1973 permissionToTake = true;
1974 permissionToDelete = true;
1975 }
1943 } 1976 }
1944 else // Auto return passes through here with null agent 1977
1978 if (permissionToTake && (!permissionToDelete))
1979 takeGroups.Add(grp);
1980
1981 if (permissionToDelete)
1945 { 1982 {
1946 permissionToTake = true; 1983 if (permissionToTake)
1947 permissionToDelete = true; 1984 deleteGroups.Add(grp);
1985 deleteIDs.Add(grp.LocalId);
1948 } 1986 }
1949 } 1987 }
1950 1988
1951 if (permissionToTake) 1989 SendKillObject(deleteIDs);
1990
1991 if (deleteGroups.Count > 0)
1952 { 1992 {
1993 foreach (SceneObjectGroup g in deleteGroups)
1994 deleteIDs.Remove(g.LocalId);
1995
1953 m_asyncSceneObjectDeleter.DeleteToInventory( 1996 m_asyncSceneObjectDeleter.DeleteToInventory(
1954 action, destinationID, deleteGroups, remoteClient, 1997 action, destinationID, deleteGroups, remoteClient,
1955 permissionToDelete); 1998 true);
1999 }
2000 if (takeGroups.Count > 0)
2001 {
2002 m_asyncSceneObjectDeleter.DeleteToInventory(
2003 action, destinationID, takeGroups, remoteClient,
2004 false);
1956 } 2005 }
1957 else if (permissionToDelete) 2006 if (deleteIDs.Count > 0)
1958 { 2007 {
1959 foreach (SceneObjectGroup g in deleteGroups) 2008 foreach (SceneObjectGroup g in deleteGroups)
1960 DeleteSceneObject(g, false); 2009 DeleteSceneObject(g, true);
1961 } 2010 }
1962 } 2011 }
1963 2012
2013 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2014 {
2015 itemID = UUID.Zero;
2016 if (grp != null)
2017 {
2018 Vector3 inventoryStoredPosition = new Vector3
2019 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
2020 ? 250
2021 : grp.AbsolutePosition.X)
2022 ,
2023 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
2024 ? 250
2025 : grp.AbsolutePosition.X,
2026 grp.AbsolutePosition.Z);
2027
2028 Vector3 originalPosition = grp.AbsolutePosition;
2029
2030 grp.AbsolutePosition = inventoryStoredPosition;
2031
2032 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2033
2034 grp.AbsolutePosition = originalPosition;
2035
2036 AssetBase asset = CreateAsset(
2037 grp.GetPartName(grp.LocalId),
2038 grp.GetPartDescription(grp.LocalId),
2039 (sbyte)AssetType.Object,
2040 Utils.StringToBytes(sceneObjectXml),
2041 remoteClient.AgentId);
2042 AssetService.Store(asset);
2043
2044 InventoryItemBase item = new InventoryItemBase();
2045 item.CreatorId = grp.RootPart.CreatorID.ToString();
2046 item.CreatorData = grp.RootPart.CreatorData;
2047 item.Owner = remoteClient.AgentId;
2048 item.ID = UUID.Random();
2049 item.AssetID = asset.FullID;
2050 item.Description = asset.Description;
2051 item.Name = asset.Name;
2052 item.AssetType = asset.Type;
2053 item.InvType = (int)InventoryType.Object;
2054
2055 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
2056 if (folder != null)
2057 item.Folder = folder.ID;
2058 else // oopsies
2059 item.Folder = UUID.Zero;
2060
2061 // Set up base perms properly
2062 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2063 permsBase &= grp.RootPart.BaseMask;
2064 permsBase |= (uint)PermissionMask.Move;
2065
2066 // Make sure we don't lock it
2067 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2068
2069 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2070 {
2071 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2072 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2073 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2074 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2075 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2076 }
2077 else
2078 {
2079 item.BasePermissions = permsBase;
2080 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2081 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2082 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2083 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2084 }
2085 item.CreationDate = Util.UnixTimeSinceEpoch();
2086
2087 // sets itemID so client can show item as 'attached' in inventory
2088 grp.SetFromItemID(item.ID);
2089
2090 if (AddInventoryItem(item))
2091 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2092 else
2093 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2094
2095 itemID = item.ID;
2096 return item.AssetID;
2097 }
2098 return UUID.Zero;
2099 }
2100
1964 /// <summary> 2101 /// <summary>
1965 /// Event Handler Rez an object into a scene 2102 /// Event Handler Rez an object into a scene
1966 /// Calls the non-void event handler 2103 /// Calls the non-void event handler
@@ -2087,6 +2224,9 @@ namespace OpenSim.Region.Framework.Scenes
2087 2224
2088 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2225 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2089 { 2226 {
2227 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2228 return;
2229
2090 SceneObjectPart part = GetSceneObjectPart(objectID); 2230 SceneObjectPart part = GetSceneObjectPart(objectID);
2091 if (part == null) 2231 if (part == null)
2092 return; 2232 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 3355ebe..b006045 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;
@@ -346,7 +348,10 @@ namespace OpenSim.Region.Framework.Scenes
346 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query); 348 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query);
347 349
348 if (accounts == null) 350 if (accounts == null)
351 {
352 m_log.DebugFormat("[LLCIENT]: ProcessAvatarPickerRequest: returned null result");
349 return; 353 return;
354 }
350 355
351 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 356 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
352 // TODO: don't create new blocks if recycling an old packet 357 // TODO: don't create new blocks if recycling an old packet
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 9e59d50..68c05f8 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -104,6 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
104 // TODO: need to figure out how allow client agents but deny 104 // TODO: need to figure out how allow client agents but deny
105 // root agents when ACL denies access to root agent 105 // root agents when ACL denies access to root agent
106 public bool m_strictAccessControl = true; 106 public bool m_strictAccessControl = true;
107 public bool m_seeIntoBannedRegion = false;
107 public int MaxUndoCount = 5; 108 public int MaxUndoCount = 5;
108 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 109 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
109 public bool LoginLock = false; 110 public bool LoginLock = false;
@@ -119,12 +120,14 @@ namespace OpenSim.Region.Framework.Scenes
119 120
120 protected int m_splitRegionID; 121 protected int m_splitRegionID;
121 protected Timer m_restartWaitTimer = new Timer(); 122 protected Timer m_restartWaitTimer = new Timer();
123 protected Timer m_timerWatchdog = new Timer();
122 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 124 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
123 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 125 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
124 protected string m_simulatorVersion = "OpenSimulator Server"; 126 protected string m_simulatorVersion = "OpenSimulator Server";
125 protected ModuleLoader m_moduleLoader; 127 protected ModuleLoader m_moduleLoader;
126 protected AgentCircuitManager m_authenticateHandler; 128 protected AgentCircuitManager m_authenticateHandler;
127 protected SceneCommunicationService m_sceneGridService; 129 protected SceneCommunicationService m_sceneGridService;
130 protected ISnmpModule m_snmpService = null;
128 131
129 protected ISimulationDataService m_SimulationDataService; 132 protected ISimulationDataService m_SimulationDataService;
130 protected IEstateDataService m_EstateDataService; 133 protected IEstateDataService m_EstateDataService;
@@ -177,7 +180,7 @@ namespace OpenSim.Region.Framework.Scenes
177 private int m_update_events = 1; 180 private int m_update_events = 1;
178 private int m_update_backup = 200; 181 private int m_update_backup = 200;
179 private int m_update_terrain = 50; 182 private int m_update_terrain = 50;
180// private int m_update_land = 1; 183 private int m_update_land = 10;
181 private int m_update_coarse_locations = 50; 184 private int m_update_coarse_locations = 50;
182 185
183 private int agentMS; 186 private int agentMS;
@@ -192,6 +195,7 @@ namespace OpenSim.Region.Framework.Scenes
192 private int landMS; 195 private int landMS;
193 private int lastCompletedFrame; 196 private int lastCompletedFrame;
194 197
198 public bool CombineRegions = false;
195 /// <summary> 199 /// <summary>
196 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 200 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
197 /// asynchronously from the update loop. 201 /// asynchronously from the update loop.
@@ -214,11 +218,14 @@ namespace OpenSim.Region.Framework.Scenes
214 private bool m_scripts_enabled = true; 218 private bool m_scripts_enabled = true;
215 private string m_defaultScriptEngine; 219 private string m_defaultScriptEngine;
216 private int m_LastLogin; 220 private int m_LastLogin;
217 private Thread HeartbeatThread; 221 private Thread HeartbeatThread = null;
218 private volatile bool shuttingdown; 222 private volatile bool shuttingdown;
219 223
220 private int m_lastUpdate; 224 private int m_lastUpdate;
225 private int m_lastIncoming;
226 private int m_lastOutgoing;
221 private bool m_firstHeartbeat = true; 227 private bool m_firstHeartbeat = true;
228 private int m_hbRestarts = 0;
222 229
223 private object m_deleting_scene_object = new object(); 230 private object m_deleting_scene_object = new object();
224 231
@@ -265,6 +272,19 @@ namespace OpenSim.Region.Framework.Scenes
265 get { return m_sceneGridService; } 272 get { return m_sceneGridService; }
266 } 273 }
267 274
275 public ISnmpModule SnmpService
276 {
277 get
278 {
279 if (m_snmpService == null)
280 {
281 m_snmpService = RequestModuleInterface<ISnmpModule>();
282 }
283
284 return m_snmpService;
285 }
286 }
287
268 public ISimulationDataService SimulationDataService 288 public ISimulationDataService SimulationDataService
269 { 289 {
270 get 290 get
@@ -546,6 +566,9 @@ namespace OpenSim.Region.Framework.Scenes
546 m_EstateDataService = estateDataService; 566 m_EstateDataService = estateDataService;
547 m_regionHandle = m_regInfo.RegionHandle; 567 m_regionHandle = m_regInfo.RegionHandle;
548 m_regionName = m_regInfo.RegionName; 568 m_regionName = m_regInfo.RegionName;
569 m_lastUpdate = Util.EnvironmentTickCount();
570 m_lastIncoming = 0;
571 m_lastOutgoing = 0;
549 572
550 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 573 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
551 m_asyncSceneObjectDeleter.Enabled = true; 574 m_asyncSceneObjectDeleter.Enabled = true;
@@ -630,96 +653,106 @@ namespace OpenSim.Region.Framework.Scenes
630 653
631 // Region config overrides global config 654 // Region config overrides global config
632 // 655 //
633 if (m_config.Configs["Startup"] != null) 656 try
634 { 657 {
635 IConfig startupConfig = m_config.Configs["Startup"]; 658 if (m_config.Configs["Startup"] != null)
659 {
660 IConfig startupConfig = m_config.Configs["Startup"];
636 661
637 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); 662 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
638 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); 663 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
639 if (!m_useBackup) 664 if (!m_useBackup)
640 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 665 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
641 666
642 //Animation states 667 //Animation states
643 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 668 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
644 669
645 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 670 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
646 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 671 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
647 672
648 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); 673 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
649 if (RegionInfo.NonphysPrimMax > 0) 674 if (RegionInfo.NonphysPrimMax > 0)
650 { 675 {
651 m_maxNonphys = RegionInfo.NonphysPrimMax; 676 m_maxNonphys = RegionInfo.NonphysPrimMax;
652 } 677 }
653 678
654 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 679 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
655 680
656 if (RegionInfo.PhysPrimMax > 0) 681 if (RegionInfo.PhysPrimMax > 0)
657 { 682 {
658 m_maxPhys = RegionInfo.PhysPrimMax; 683 m_maxPhys = RegionInfo.PhysPrimMax;
659 } 684 }
660 685
661 // Here, if clamping is requested in either global or 686 // Here, if clamping is requested in either global or
662 // local config, it will be used 687 // local config, it will be used
663 // 688 //
664 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize); 689 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
665 if (RegionInfo.ClampPrimSize) 690 if (RegionInfo.ClampPrimSize)
666 { 691 {
667 m_clampPrimSize = true; 692 m_clampPrimSize = true;
668 } 693 }
669 694
670 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 695 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
671 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 696 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
672 m_dontPersistBefore = 697 m_dontPersistBefore =
673 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); 698 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
674 m_dontPersistBefore *= 10000000; 699 m_dontPersistBefore *= 10000000;
675 m_persistAfter = 700 m_persistAfter =
676 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); 701 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
677 m_persistAfter *= 10000000; 702 m_persistAfter *= 10000000;
678 703
679 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 704 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
705 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
680 706
681 IConfig packetConfig = m_config.Configs["PacketPool"]; 707 IConfig packetConfig = m_config.Configs["PacketPool"];
682 if (packetConfig != null) 708 if (packetConfig != null)
683 { 709 {
684 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); 710 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
685 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); 711 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
686 } 712 }
687 713
688 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 714 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
715 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
716 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
689 717
690 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 718 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
691 if (m_generateMaptiles) 719 if (m_generateMaptiles)
692 {
693 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
694 if (maptileRefresh != 0)
695 { 720 {
696 m_mapGenerationTimer.Interval = maptileRefresh * 1000; 721 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
697 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister; 722 if (maptileRefresh != 0)
698 m_mapGenerationTimer.AutoReset = true; 723 {
699 m_mapGenerationTimer.Start(); 724 m_mapGenerationTimer.Interval = maptileRefresh * 1000;
725 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister;
726 m_mapGenerationTimer.AutoReset = true;
727 m_mapGenerationTimer.Start();
728 }
700 } 729 }
701 } 730 else
702 else
703 {
704 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
705 UUID tileID;
706
707 if (UUID.TryParse(tile, out tileID))
708 { 731 {
709 RegionInfo.RegionSettings.TerrainImageID = tileID; 732 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
733 UUID tileID;
734
735 if (UUID.TryParse(tile, out tileID))
736 {
737 RegionInfo.RegionSettings.TerrainImageID = tileID;
738 }
710 } 739 }
711 }
712 740
713 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime); 741 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
714 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup); 742 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup);
715 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 743 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
716 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement); 744 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement);
717 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events); 745 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events);
718 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects); 746 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
719 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics); 747 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
720 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); 748 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
721 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 749 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
722 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 750 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
751 }
752 }
753 catch (Exception e)
754 {
755 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
723 } 756 }
724 757
725 #endregion Region Config 758 #endregion Region Config
@@ -1128,7 +1161,22 @@ namespace OpenSim.Region.Framework.Scenes
1128 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1161 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1129 if (HeartbeatThread != null) 1162 if (HeartbeatThread != null)
1130 { 1163 {
1164 m_hbRestarts++;
1165 if(m_hbRestarts > 10)
1166 Environment.Exit(1);
1167 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1168
1169//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1170//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1171//proc.EnableRaisingEvents=false;
1172//proc.StartInfo.FileName = "/bin/kill";
1173//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1174//proc.Start();
1175//proc.WaitForExit();
1176//Thread.Sleep(1000);
1177//Environment.Exit(1);
1131 HeartbeatThread.Abort(); 1178 HeartbeatThread.Abort();
1179 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId);
1132 HeartbeatThread = null; 1180 HeartbeatThread = null;
1133 } 1181 }
1134 m_lastUpdate = Util.EnvironmentTickCount(); 1182 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1182,9 +1230,6 @@ namespace OpenSim.Region.Framework.Scenes
1182 1230
1183 while (!shuttingdown) 1231 while (!shuttingdown)
1184 Update(); 1232 Update();
1185
1186 m_lastUpdate = Util.EnvironmentTickCount();
1187 m_firstHeartbeat = false;
1188 } 1233 }
1189 catch (ThreadAbortException) 1234 catch (ThreadAbortException)
1190 { 1235 {
@@ -1282,6 +1327,13 @@ namespace OpenSim.Region.Framework.Scenes
1282 eventMS = Util.EnvironmentTickCountSubtract(evMS); ; 1327 eventMS = Util.EnvironmentTickCountSubtract(evMS); ;
1283 } 1328 }
1284 1329
1330 // if (Frame % m_update_land == 0)
1331 // {
1332 // int ldMS = Util.EnvironmentTickCount();
1333 // UpdateLand();
1334 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1335 // }
1336
1285 if (Frame % m_update_backup == 0) 1337 if (Frame % m_update_backup == 0)
1286 { 1338 {
1287 int backMS = Util.EnvironmentTickCount(); 1339 int backMS = Util.EnvironmentTickCount();
@@ -1375,12 +1427,16 @@ namespace OpenSim.Region.Framework.Scenes
1375 maintc = Util.EnvironmentTickCountSubtract(maintc); 1427 maintc = Util.EnvironmentTickCountSubtract(maintc);
1376 maintc = (int)(MinFrameTime * 1000) - maintc; 1428 maintc = (int)(MinFrameTime * 1000) - maintc;
1377 1429
1430
1431 m_lastUpdate = Util.EnvironmentTickCount();
1432 m_firstHeartbeat = false;
1433
1378 if (maintc > 0) 1434 if (maintc > 0)
1379 Thread.Sleep(maintc); 1435 Thread.Sleep(maintc);
1380 1436
1381 // Tell the watchdog that this thread is still alive 1437 // Tell the watchdog that this thread is still alive
1382 Watchdog.UpdateThread(); 1438 Watchdog.UpdateThread();
1383 } 1439 }
1384 1440
1385 public void AddGroupTarget(SceneObjectGroup grp) 1441 public void AddGroupTarget(SceneObjectGroup grp)
1386 { 1442 {
@@ -1396,9 +1452,9 @@ namespace OpenSim.Region.Framework.Scenes
1396 1452
1397 private void CheckAtTargets() 1453 private void CheckAtTargets()
1398 { 1454 {
1399 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1455 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1400 lock (m_groupsWithTargets) 1456 lock (m_groupsWithTargets)
1401 objs = m_groupsWithTargets.Values; 1457 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1402 1458
1403 foreach (SceneObjectGroup entry in objs) 1459 foreach (SceneObjectGroup entry in objs)
1404 entry.checkAtTargets(); 1460 entry.checkAtTargets();
@@ -1479,7 +1535,7 @@ namespace OpenSim.Region.Framework.Scenes
1479 msg.fromAgentName = "Server"; 1535 msg.fromAgentName = "Server";
1480 msg.dialog = (byte)19; // Object msg 1536 msg.dialog = (byte)19; // Object msg
1481 msg.fromGroup = false; 1537 msg.fromGroup = false;
1482 msg.offline = (byte)0; 1538 msg.offline = (byte)1;
1483 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1539 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1484 msg.Position = Vector3.Zero; 1540 msg.Position = Vector3.Zero;
1485 msg.RegionID = RegionInfo.RegionID.Guid; 1541 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1710,14 +1766,24 @@ namespace OpenSim.Region.Framework.Scenes
1710 /// <returns></returns> 1766 /// <returns></returns>
1711 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1767 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1712 { 1768 {
1769
1770 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1771 Vector3 wpos = Vector3.Zero;
1772 // Check for water surface intersection from above
1773 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1774 {
1775 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1776 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1777 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1778 wpos.Z = wheight;
1779 }
1780
1713 Vector3 pos = Vector3.Zero; 1781 Vector3 pos = Vector3.Zero;
1714 if (RayEndIsIntersection == (byte)1) 1782 if (RayEndIsIntersection == (byte)1)
1715 { 1783 {
1716 pos = RayEnd; 1784 pos = RayEnd;
1717 return pos;
1718 } 1785 }
1719 1786 else if (RayTargetID != UUID.Zero)
1720 if (RayTargetID != UUID.Zero)
1721 { 1787 {
1722 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1788 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1723 1789
@@ -1739,7 +1805,7 @@ namespace OpenSim.Region.Framework.Scenes
1739 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1805 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1740 1806
1741 // Un-comment out the following line to Get Raytrace results printed to the console. 1807 // Un-comment out the following line to Get Raytrace results printed to the console.
1742 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1808 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1743 float ScaleOffset = 0.5f; 1809 float ScaleOffset = 0.5f;
1744 1810
1745 // If we hit something 1811 // If we hit something
@@ -1762,13 +1828,10 @@ namespace OpenSim.Region.Framework.Scenes
1762 //pos.Z -= 0.25F; 1828 //pos.Z -= 0.25F;
1763 1829
1764 } 1830 }
1765
1766 return pos;
1767 } 1831 }
1768 else 1832 else
1769 { 1833 {
1770 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1834 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1771
1772 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1835 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1773 1836
1774 // Un-comment the following line to print the raytrace results to the console. 1837 // Un-comment the following line to print the raytrace results to the console.
@@ -1777,13 +1840,12 @@ namespace OpenSim.Region.Framework.Scenes
1777 if (ei.HitTF) 1840 if (ei.HitTF)
1778 { 1841 {
1779 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1842 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1780 } else 1843 }
1844 else
1781 { 1845 {
1782 // fall back to our stupid functionality 1846 // fall back to our stupid functionality
1783 pos = RayEnd; 1847 pos = RayEnd;
1784 } 1848 }
1785
1786 return pos;
1787 } 1849 }
1788 } 1850 }
1789 else 1851 else
@@ -1794,8 +1856,12 @@ namespace OpenSim.Region.Framework.Scenes
1794 //increase height so its above the ground. 1856 //increase height so its above the ground.
1795 //should be getting the normal of the ground at the rez point and using that? 1857 //should be getting the normal of the ground at the rez point and using that?
1796 pos.Z += scale.Z / 2f; 1858 pos.Z += scale.Z / 2f;
1797 return pos; 1859// return pos;
1798 } 1860 }
1861
1862 // check against posible water intercept
1863 if (wpos.Z > pos.Z) pos = wpos;
1864 return pos;
1799 } 1865 }
1800 1866
1801 1867
@@ -1879,7 +1945,10 @@ namespace OpenSim.Region.Framework.Scenes
1879 public bool AddRestoredSceneObject( 1945 public bool AddRestoredSceneObject(
1880 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1946 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1881 { 1947 {
1882 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1948 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1949 if (result)
1950 sceneObject.IsDeleted = false;
1951 return result;
1883 } 1952 }
1884 1953
1885 /// <summary> 1954 /// <summary>
@@ -1971,6 +2040,15 @@ namespace OpenSim.Region.Framework.Scenes
1971 /// </summary> 2040 /// </summary>
1972 public void DeleteAllSceneObjects() 2041 public void DeleteAllSceneObjects()
1973 { 2042 {
2043 DeleteAllSceneObjects(false);
2044 }
2045
2046 /// <summary>
2047 /// Delete every object from the scene. This does not include attachments worn by avatars.
2048 /// </summary>
2049 public void DeleteAllSceneObjects(bool exceptNoCopy)
2050 {
2051 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1974 lock (Entities) 2052 lock (Entities)
1975 { 2053 {
1976 EntityBase[] entities = Entities.GetEntities(); 2054 EntityBase[] entities = Entities.GetEntities();
@@ -1979,11 +2057,24 @@ namespace OpenSim.Region.Framework.Scenes
1979 if (e is SceneObjectGroup) 2057 if (e is SceneObjectGroup)
1980 { 2058 {
1981 SceneObjectGroup sog = (SceneObjectGroup)e; 2059 SceneObjectGroup sog = (SceneObjectGroup)e;
1982 if (!sog.IsAttachment) 2060 if (sog != null && !sog.IsAttachment)
1983 DeleteSceneObject((SceneObjectGroup)e, false); 2061 {
2062 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2063 {
2064 DeleteSceneObject((SceneObjectGroup)e, false);
2065 }
2066 else
2067 {
2068 toReturn.Add((SceneObjectGroup)e);
2069 }
2070 }
1984 } 2071 }
1985 } 2072 }
1986 } 2073 }
2074 if (toReturn.Count > 0)
2075 {
2076 returnObjects(toReturn.ToArray(), UUID.Zero);
2077 }
1987 } 2078 }
1988 2079
1989 /// <summary> 2080 /// <summary>
@@ -2031,6 +2122,8 @@ namespace OpenSim.Region.Framework.Scenes
2031 } 2122 }
2032 2123
2033 group.DeleteGroupFromScene(silent); 2124 group.DeleteGroupFromScene(silent);
2125 if (!silent)
2126 SendKillObject(new List<uint>() { group.LocalId });
2034 2127
2035// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2128// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2036 } 2129 }
@@ -2320,6 +2413,8 @@ namespace OpenSim.Region.Framework.Scenes
2320 2413
2321 if (newPosition != Vector3.Zero) 2414 if (newPosition != Vector3.Zero)
2322 newObject.RootPart.GroupPosition = newPosition; 2415 newObject.RootPart.GroupPosition = newPosition;
2416 if (newObject.RootPart.KeyframeMotion != null)
2417 newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2323 2418
2324 if (!AddSceneObject(newObject)) 2419 if (!AddSceneObject(newObject))
2325 { 2420 {
@@ -2388,10 +2483,17 @@ namespace OpenSim.Region.Framework.Scenes
2388 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2483 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2389 public bool AddSceneObject(SceneObjectGroup sceneObject) 2484 public bool AddSceneObject(SceneObjectGroup sceneObject)
2390 { 2485 {
2486 if (sceneObject.OwnerID == UUID.Zero)
2487 {
2488 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2489 return false;
2490 }
2491
2391 // If the user is banned, we won't let any of their objects 2492 // If the user is banned, we won't let any of their objects
2392 // enter. Period. 2493 // enter. Period.
2393 // 2494 //
2394 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2495 int flags = GetUserFlags(sceneObject.OwnerID);
2496 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2395 { 2497 {
2396 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2498 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2397 2499
@@ -2437,12 +2539,23 @@ namespace OpenSim.Region.Framework.Scenes
2437 } 2539 }
2438 else 2540 else
2439 { 2541 {
2542 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2440 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2543 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2441 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2544 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2442 } 2545 }
2546 if (sceneObject.OwnerID == UUID.Zero)
2547 {
2548 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2549 return false;
2550 }
2443 } 2551 }
2444 else 2552 else
2445 { 2553 {
2554 if (sceneObject.OwnerID == UUID.Zero)
2555 {
2556 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2557 return false;
2558 }
2446 AddRestoredSceneObject(sceneObject, true, false); 2559 AddRestoredSceneObject(sceneObject, true, false);
2447 2560
2448 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2561 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2471,6 +2584,24 @@ namespace OpenSim.Region.Framework.Scenes
2471 return 2; // StateSource.PrimCrossing 2584 return 2; // StateSource.PrimCrossing
2472 } 2585 }
2473 2586
2587 public int GetUserFlags(UUID user)
2588 {
2589 //Unfortunately the SP approach means that the value is cached until region is restarted
2590 /*
2591 ScenePresence sp;
2592 if (TryGetScenePresence(user, out sp))
2593 {
2594 return sp.UserFlags;
2595 }
2596 else
2597 {
2598 */
2599 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2600 if (uac == null)
2601 return 0;
2602 return uac.UserFlags;
2603 //}
2604 }
2474 #endregion 2605 #endregion
2475 2606
2476 #region Add/Remove Avatar Methods 2607 #region Add/Remove Avatar Methods
@@ -2485,6 +2616,7 @@ namespace OpenSim.Region.Framework.Scenes
2485 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2616 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2486 2617
2487 CheckHeartbeat(); 2618 CheckHeartbeat();
2619 ScenePresence presence;
2488 2620
2489 ScenePresence sp = GetScenePresence(client.AgentId); 2621 ScenePresence sp = GetScenePresence(client.AgentId);
2490 2622
@@ -2533,7 +2665,13 @@ namespace OpenSim.Region.Framework.Scenes
2533 2665
2534 EventManager.TriggerOnNewClient(client); 2666 EventManager.TriggerOnNewClient(client);
2535 if (vialogin) 2667 if (vialogin)
2668 {
2536 EventManager.TriggerOnClientLogin(client); 2669 EventManager.TriggerOnClientLogin(client);
2670 // Send initial parcel data
2671 Vector3 pos = sp.AbsolutePosition;
2672 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2673 land.SendLandUpdateToClient(client);
2674 }
2537 2675
2538 return sp; 2676 return sp;
2539 } 2677 }
@@ -2623,19 +2761,12 @@ namespace OpenSim.Region.Framework.Scenes
2623 // and the scene presence and the client, if they exist 2761 // and the scene presence and the client, if they exist
2624 try 2762 try
2625 { 2763 {
2626 // We need to wait for the client to make UDP contact first. 2764 ScenePresence sp = GetScenePresence(agentID);
2627 // It's the UDP contact that creates the scene presence 2765 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2628 ScenePresence sp = WaitGetScenePresence(agentID); 2766
2629 if (sp != null) 2767 if (sp != null)
2630 {
2631 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2632
2633 sp.ControllingClient.Close(); 2768 sp.ControllingClient.Close();
2634 } 2769
2635 else
2636 {
2637 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2638 }
2639 // BANG! SLASH! 2770 // BANG! SLASH!
2640 m_authenticateHandler.RemoveCircuit(agentID); 2771 m_authenticateHandler.RemoveCircuit(agentID);
2641 2772
@@ -2736,6 +2867,7 @@ namespace OpenSim.Region.Framework.Scenes
2736 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2867 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2737 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2868 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2738 client.OnCopyInventoryItem += CopyInventoryItem; 2869 client.OnCopyInventoryItem += CopyInventoryItem;
2870 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2739 client.OnMoveInventoryItem += MoveInventoryItem; 2871 client.OnMoveInventoryItem += MoveInventoryItem;
2740 client.OnRemoveInventoryItem += RemoveInventoryItem; 2872 client.OnRemoveInventoryItem += RemoveInventoryItem;
2741 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2873 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2911,15 +3043,16 @@ namespace OpenSim.Region.Framework.Scenes
2911 /// </summary> 3043 /// </summary>
2912 /// <param name="agentId">The avatar's Unique ID</param> 3044 /// <param name="agentId">The avatar's Unique ID</param>
2913 /// <param name="client">The IClientAPI for the client</param> 3045 /// <param name="client">The IClientAPI for the client</param>
2914 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3046 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2915 { 3047 {
2916 if (m_teleportModule != null) 3048 if (m_teleportModule != null)
2917 m_teleportModule.TeleportHome(agentId, client); 3049 return m_teleportModule.TeleportHome(agentId, client);
2918 else 3050 else
2919 { 3051 {
2920 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3052 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2921 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3053 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2922 } 3054 }
3055 return false;
2923 } 3056 }
2924 3057
2925 /// <summary> 3058 /// <summary>
@@ -3029,6 +3162,16 @@ namespace OpenSim.Region.Framework.Scenes
3029 /// <param name="flags"></param> 3162 /// <param name="flags"></param>
3030 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3163 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3031 { 3164 {
3165 //Add half the avatar's height so that the user doesn't fall through prims
3166 ScenePresence presence;
3167 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3168 {
3169 if (presence.Appearance != null)
3170 {
3171 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3172 }
3173 }
3174
3032 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3175 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3033 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3176 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3034 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3177 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3097,8 +3240,9 @@ namespace OpenSim.Region.Framework.Scenes
3097 regions.Remove(RegionInfo.RegionHandle); 3240 regions.Remove(RegionInfo.RegionHandle);
3098 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3241 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3099 } 3242 }
3100 3243 m_log.Debug("[Scene] Beginning ClientClosed");
3101 m_eventManager.TriggerClientClosed(agentID, this); 3244 m_eventManager.TriggerClientClosed(agentID, this);
3245 m_log.Debug("[Scene] Finished ClientClosed");
3102 } 3246 }
3103 catch (NullReferenceException) 3247 catch (NullReferenceException)
3104 { 3248 {
@@ -3160,9 +3304,10 @@ namespace OpenSim.Region.Framework.Scenes
3160 { 3304 {
3161 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3305 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3162 } 3306 }
3163 3307 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3164 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3308 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3165// CleanDroppedAttachments(); 3309// CleanDroppedAttachments();
3310 m_log.Debug("[Scene] The avatar has left the building");
3166 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3311 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3167 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3312 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3168 } 3313 }
@@ -3284,13 +3429,16 @@ namespace OpenSim.Region.Framework.Scenes
3284 sp = null; 3429 sp = null;
3285 } 3430 }
3286 3431
3287 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3288 3432
3289 //On login test land permisions 3433 //On login test land permisions
3290 if (vialogin) 3434 if (vialogin)
3291 { 3435 {
3292 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3436 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3437 if (cache != null)
3438 cache.Remove(agent.firstname + " " + agent.lastname);
3439 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3293 { 3440 {
3441 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3294 return false; 3442 return false;
3295 } 3443 }
3296 } 3444 }
@@ -3314,8 +3462,13 @@ namespace OpenSim.Region.Framework.Scenes
3314 3462
3315 try 3463 try
3316 { 3464 {
3317 if (!AuthorizeUser(agent, out reason)) 3465 // Always check estate if this is a login. Always
3318 return false; 3466 // check if banned regions are to be blacked out.
3467 if (vialogin || (!m_seeIntoBannedRegion))
3468 {
3469 if (!AuthorizeUser(agent, out reason))
3470 return false;
3471 }
3319 } 3472 }
3320 catch (Exception e) 3473 catch (Exception e)
3321 { 3474 {
@@ -3441,6 +3594,8 @@ namespace OpenSim.Region.Framework.Scenes
3441 } 3594 }
3442 3595
3443 // Honor parcel landing type and position. 3596 // Honor parcel landing type and position.
3597 /*
3598 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3444 if (land != null) 3599 if (land != null)
3445 { 3600 {
3446 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3601 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3448,26 +3603,34 @@ namespace OpenSim.Region.Framework.Scenes
3448 agent.startpos = land.LandData.UserLocation; 3603 agent.startpos = land.LandData.UserLocation;
3449 } 3604 }
3450 } 3605 }
3606 */// This is now handled properly in ScenePresence.MakeRootAgent
3451 } 3607 }
3452 3608
3453 return true; 3609 return true;
3454 } 3610 }
3455 3611
3456 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3612 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3457 { 3613 {
3458 3614 reason = String.Empty;
3459 bool banned = land.IsBannedFromLand(agent.AgentID); 3615 if (Permissions.IsGod(agentID))
3460 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3616 return true;
3617
3618 ILandObject land = LandChannel.GetLandObject(posX, posY);
3619 if (land == null)
3620 return false;
3621
3622 bool banned = land.IsBannedFromLand(agentID);
3623 bool restricted = land.IsRestrictedFromLand(agentID);
3461 3624
3462 if (banned || restricted) 3625 if (banned || restricted)
3463 { 3626 {
3464 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3627 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3465 if (nearestParcel != null) 3628 if (nearestParcel != null)
3466 { 3629 {
3467 //Move agent to nearest allowed 3630 //Move agent to nearest allowed
3468 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3631 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3469 agent.startpos.X = newPosition.X; 3632 posX = newPosition.X;
3470 agent.startpos.Y = newPosition.Y; 3633 posY = newPosition.Y;
3471 } 3634 }
3472 else 3635 else
3473 { 3636 {
@@ -3529,7 +3692,7 @@ namespace OpenSim.Region.Framework.Scenes
3529 3692
3530 if (!m_strictAccessControl) return true; 3693 if (!m_strictAccessControl) return true;
3531 if (Permissions.IsGod(agent.AgentID)) return true; 3694 if (Permissions.IsGod(agent.AgentID)) return true;
3532 3695
3533 if (AuthorizationService != null) 3696 if (AuthorizationService != null)
3534 { 3697 {
3535 if (!AuthorizationService.IsAuthorizedForRegion( 3698 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3537,14 +3700,14 @@ namespace OpenSim.Region.Framework.Scenes
3537 { 3700 {
3538 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3701 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3539 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3702 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3540 3703
3541 return false; 3704 return false;
3542 } 3705 }
3543 } 3706 }
3544 3707
3545 if (m_regInfo.EstateSettings != null) 3708 if (m_regInfo.EstateSettings != null)
3546 { 3709 {
3547 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3710 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3548 { 3711 {
3549 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3712 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3550 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3713 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3736,6 +3899,13 @@ namespace OpenSim.Region.Framework.Scenes
3736 3899
3737 // We have to wait until the viewer contacts this region after receiving EAC. 3900 // We have to wait until the viewer contacts this region after receiving EAC.
3738 // That calls AddNewClient, which finally creates the ScenePresence 3901 // That calls AddNewClient, which finally creates the ScenePresence
3902 int flags = GetUserFlags(cAgentData.AgentID);
3903 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3904 {
3905 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3906 return false;
3907 }
3908
3739 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3909 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3740 if (nearestParcel == null) 3910 if (nearestParcel == null)
3741 { 3911 {
@@ -3817,12 +3987,22 @@ namespace OpenSim.Region.Framework.Scenes
3817 return false; 3987 return false;
3818 } 3988 }
3819 3989
3990 public bool IncomingCloseAgent(UUID agentID)
3991 {
3992 return IncomingCloseAgent(agentID, false);
3993 }
3994
3995 public bool IncomingCloseChildAgent(UUID agentID)
3996 {
3997 return IncomingCloseAgent(agentID, true);
3998 }
3999
3820 /// <summary> 4000 /// <summary>
3821 /// Tell a single agent to disconnect from the region. 4001 /// Tell a single agent to disconnect from the region.
3822 /// </summary> 4002 /// </summary>
3823 /// <param name="regionHandle"></param>
3824 /// <param name="agentID"></param> 4003 /// <param name="agentID"></param>
3825 public bool IncomingCloseAgent(UUID agentID) 4004 /// <param name="childOnly"></param>
4005 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3826 { 4006 {
3827 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4007 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3828 4008
@@ -3834,7 +4014,7 @@ namespace OpenSim.Region.Framework.Scenes
3834 { 4014 {
3835 m_sceneGraph.removeUserCount(false); 4015 m_sceneGraph.removeUserCount(false);
3836 } 4016 }
3837 else 4017 else if (!childOnly)
3838 { 4018 {
3839 m_sceneGraph.removeUserCount(true); 4019 m_sceneGraph.removeUserCount(true);
3840 } 4020 }
@@ -3850,9 +4030,12 @@ namespace OpenSim.Region.Framework.Scenes
3850 } 4030 }
3851 else 4031 else
3852 presence.ControllingClient.SendShutdownConnectionNotice(); 4032 presence.ControllingClient.SendShutdownConnectionNotice();
4033 presence.ControllingClient.Close(false);
4034 }
4035 else if (!childOnly)
4036 {
4037 presence.ControllingClient.Close(true);
3853 } 4038 }
3854
3855 presence.ControllingClient.Close();
3856 return true; 4039 return true;
3857 } 4040 }
3858 4041
@@ -4434,34 +4617,78 @@ namespace OpenSim.Region.Framework.Scenes
4434 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4617 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4435 } 4618 }
4436 4619
4437 public int GetHealth() 4620 public int GetHealth(out int flags, out string message)
4438 { 4621 {
4439 // Returns: 4622 // Returns:
4440 // 1 = sim is up and accepting http requests. The heartbeat has 4623 // 1 = sim is up and accepting http requests. The heartbeat has
4441 // stopped and the sim is probably locked up, but a remote 4624 // stopped and the sim is probably locked up, but a remote
4442 // admin restart may succeed 4625 // admin restart may succeed
4443 // 4626 //
4444 // 2 = Sim is up and the heartbeat is running. The sim is likely 4627 // 2 = Sim is up and the heartbeat is running. The sim is likely
4445 // usable for people within and logins _may_ work 4628 // usable for people within
4446 // 4629 //
4447 // 3 = We have seen a new user enter within the past 4 minutes 4630 // 3 = Sim is up and one packet thread is running. Sim is
4631 // unstable and will not accept new logins
4632 //
4633 // 4 = Sim is up and both packet threads are running. Sim is
4634 // likely usable
4635 //
4636 // 5 = We have seen a new user enter within the past 4 minutes
4448 // which can be seen as positive confirmation of sim health 4637 // which can be seen as positive confirmation of sim health
4449 // 4638 //
4639
4640 flags = 0;
4641 message = String.Empty;
4642
4643 CheckHeartbeat();
4644
4645 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4646 {
4647 // We're still starting
4648 // 0 means "in startup", it can't happen another way, since
4649 // to get here, we must be able to accept http connections
4650 return 0;
4651 }
4652
4450 int health=1; // Start at 1, means we're up 4653 int health=1; // Start at 1, means we're up
4451 4654
4452 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4655 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4656 {
4657 health+=1;
4658 flags |= 1;
4659 }
4660
4661 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4662 {
4453 health+=1; 4663 health+=1;
4664 flags |= 2;
4665 }
4666
4667 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4668 {
4669 health+=1;
4670 flags |= 4;
4671 }
4454 else 4672 else
4673 {
4674int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4675System.Diagnostics.Process proc = new System.Diagnostics.Process();
4676proc.EnableRaisingEvents=false;
4677proc.StartInfo.FileName = "/bin/kill";
4678proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4679proc.Start();
4680proc.WaitForExit();
4681Thread.Sleep(1000);
4682Environment.Exit(1);
4683 }
4684
4685 if (flags != 7)
4455 return health; 4686 return health;
4456 4687
4457 // A login in the last 4 mins? We can't be doing too badly 4688 // A login in the last 4 mins? We can't be doing too badly
4458 // 4689 //
4459 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4690 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4460 health++; 4691 health++;
4461 else
4462 return health;
4463
4464 CheckHeartbeat();
4465 4692
4466 return health; 4693 return health;
4467 } 4694 }
@@ -4550,7 +4777,7 @@ namespace OpenSim.Region.Framework.Scenes
4550 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 4777 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
4551 if (wasUsingPhysics) 4778 if (wasUsingPhysics)
4552 { 4779 {
4553 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 4780 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
4554 } 4781 }
4555 } 4782 }
4556 4783
@@ -4654,7 +4881,7 @@ namespace OpenSim.Region.Framework.Scenes
4654 if (m_firstHeartbeat) 4881 if (m_firstHeartbeat)
4655 return; 4882 return;
4656 4883
4657 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4884 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4658 StartTimer(); 4885 StartTimer();
4659 } 4886 }
4660 4887
@@ -4668,9 +4895,14 @@ namespace OpenSim.Region.Framework.Scenes
4668 get { return m_allowScriptCrossings; } 4895 get { return m_allowScriptCrossings; }
4669 } 4896 }
4670 4897
4671 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 4898 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
4899 {
4900 return GetNearestAllowedPosition(avatar, null);
4901 }
4902
4903 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
4672 { 4904 {
4673 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 4905 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4674 4906
4675 if (nearestParcel != null) 4907 if (nearestParcel != null)
4676 { 4908 {
@@ -4679,10 +4911,7 @@ namespace OpenSim.Region.Framework.Scenes
4679 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 4911 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4680 if (nearestPoint != null) 4912 if (nearestPoint != null)
4681 { 4913 {
4682// m_log.DebugFormat( 4914 Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
4683// "[SCENE]: Found a sane previous position based on velocity for {0}, sending them to {1} in {2}",
4684// avatar.Name, nearestPoint, nearestParcel.LandData.Name);
4685
4686 return nearestPoint.Value; 4915 return nearestPoint.Value;
4687 } 4916 }
4688 4917
@@ -4692,17 +4921,20 @@ namespace OpenSim.Region.Framework.Scenes
4692 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 4921 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4693 if (nearestPoint != null) 4922 if (nearestPoint != null)
4694 { 4923 {
4695// m_log.DebugFormat( 4924 Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString());
4696// "[SCENE]: {0} had a zero velocity, sending them to {1}", avatar.Name, nearestPoint);
4697
4698 return nearestPoint.Value; 4925 return nearestPoint.Value;
4699 } 4926 }
4700 4927
4701 //Ultimate backup if we have no idea where they are 4928 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
4702// m_log.DebugFormat( 4929 if (dest != excludeParcel)
4703// "[SCENE]: No idea where {0} is, sending them to {1}", avatar.Name, avatar.lastKnownAllowedPosition); 4930 {
4931 // Ultimate backup if we have no idea where they are and
4932 // the last allowed position was in another parcel
4933 Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
4934 return avatar.lastKnownAllowedPosition;
4935 }
4704 4936
4705 return avatar.lastKnownAllowedPosition; 4937 // else fall through to region edge
4706 } 4938 }
4707 4939
4708 //Go to the edge, this happens in teleporting to a region with no available parcels 4940 //Go to the edge, this happens in teleporting to a region with no available parcels
@@ -4736,13 +4968,18 @@ namespace OpenSim.Region.Framework.Scenes
4736 4968
4737 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 4969 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4738 { 4970 {
4971 return GetNearestAllowedParcel(avatarId, x, y, null);
4972 }
4973
4974 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
4975 {
4739 List<ILandObject> all = AllParcels(); 4976 List<ILandObject> all = AllParcels();
4740 float minParcelDistance = float.MaxValue; 4977 float minParcelDistance = float.MaxValue;
4741 ILandObject nearestParcel = null; 4978 ILandObject nearestParcel = null;
4742 4979
4743 foreach (var parcel in all) 4980 foreach (var parcel in all)
4744 { 4981 {
4745 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 4982 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4746 { 4983 {
4747 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 4984 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4748 if (parcelDistance < minParcelDistance) 4985 if (parcelDistance < minParcelDistance)
@@ -4984,7 +5221,55 @@ namespace OpenSim.Region.Framework.Scenes
4984 mapModule.GenerateMaptile(); 5221 mapModule.GenerateMaptile();
4985 } 5222 }
4986 5223
4987 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5224// public void CleanDroppedAttachments()
5225// {
5226// List<SceneObjectGroup> objectsToDelete =
5227// new List<SceneObjectGroup>();
5228//
5229// lock (m_cleaningAttachments)
5230// {
5231// ForEachSOG(delegate (SceneObjectGroup grp)
5232// {
5233// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5234// {
5235// UUID agentID = grp.OwnerID;
5236// if (agentID == UUID.Zero)
5237// {
5238// objectsToDelete.Add(grp);
5239// return;
5240// }
5241//
5242// ScenePresence sp = GetScenePresence(agentID);
5243// if (sp == null)
5244// {
5245// objectsToDelete.Add(grp);
5246// return;
5247// }
5248// }
5249// });
5250// }
5251//
5252// foreach (SceneObjectGroup grp in objectsToDelete)
5253// {
5254// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5255// DeleteSceneObject(grp, true);
5256// }
5257// }
5258
5259 public void ThreadAlive(int threadCode)
5260 {
5261 switch(threadCode)
5262 {
5263 case 1: // Incoming
5264 m_lastIncoming = Util.EnvironmentTickCount();
5265 break;
5266 case 2: // Incoming
5267 m_lastOutgoing = Util.EnvironmentTickCount();
5268 break;
5269 }
5270 }
5271
5272 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
4988 { 5273 {
4989 RegenerateMaptile(); 5274 RegenerateMaptile();
4990 5275
@@ -5003,6 +5288,14 @@ namespace OpenSim.Region.Framework.Scenes
5003 // child agent creation, thereby emulating the SL behavior. 5288 // child agent creation, thereby emulating the SL behavior.
5004 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5289 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5005 { 5290 {
5291 reason = "You are banned from the region";
5292
5293 if (Permissions.IsGod(agentID))
5294 {
5295 reason = String.Empty;
5296 return true;
5297 }
5298
5006 int num = m_sceneGraph.GetNumberOfScenePresences(); 5299 int num = m_sceneGraph.GetNumberOfScenePresences();
5007 5300
5008 if (num >= RegionInfo.RegionSettings.AgentLimit) 5301 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5014,6 +5307,41 @@ namespace OpenSim.Region.Framework.Scenes
5014 } 5307 }
5015 } 5308 }
5016 5309
5310 ScenePresence presence = GetScenePresence(agentID);
5311 IClientAPI client = null;
5312 AgentCircuitData aCircuit = null;
5313
5314 if (presence != null)
5315 {
5316 client = presence.ControllingClient;
5317 if (client != null)
5318 aCircuit = client.RequestClientInfo();
5319 }
5320
5321 // We may be called before there is a presence or a client.
5322 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5323 if (client == null)
5324 {
5325 aCircuit = new AgentCircuitData();
5326 aCircuit.AgentID = agentID;
5327 aCircuit.firstname = String.Empty;
5328 aCircuit.lastname = String.Empty;
5329 }
5330
5331 try
5332 {
5333 if (!AuthorizeUser(aCircuit, out reason))
5334 {
5335 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5336 return false;
5337 }
5338 }
5339 catch (Exception e)
5340 {
5341 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5342 return false;
5343 }
5344
5017 if (position == Vector3.Zero) // Teleport 5345 if (position == Vector3.Zero) // Teleport
5018 { 5346 {
5019 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5347 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5042,13 +5370,46 @@ namespace OpenSim.Region.Framework.Scenes
5042 } 5370 }
5043 } 5371 }
5044 } 5372 }
5373
5374 float posX = 128.0f;
5375 float posY = 128.0f;
5376
5377 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5378 {
5379 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5380 return false;
5381 }
5382 }
5383 else // Walking
5384 {
5385 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5386 if (land == null)
5387 return false;
5388
5389 bool banned = land.IsBannedFromLand(agentID);
5390 bool restricted = land.IsRestrictedFromLand(agentID);
5391
5392 if (banned || restricted)
5393 return false;
5045 } 5394 }
5046 5395
5047 reason = String.Empty; 5396 reason = String.Empty;
5048 return true; 5397 return true;
5049 } 5398 }
5050 5399
5051 /// <summary> 5400 public void StartTimerWatchdog()
5401 {
5402 m_timerWatchdog.Interval = 1000;
5403 m_timerWatchdog.Elapsed += TimerWatchdog;
5404 m_timerWatchdog.AutoReset = true;
5405 m_timerWatchdog.Start();
5406 }
5407
5408 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5409 {
5410 CheckHeartbeat();
5411 }
5412
5052 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5413 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5053 /// autopilot that moves an avatar to a sit target!. 5414 /// autopilot that moves an avatar to a sit target!.
5054 /// </summary> 5415 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 495cede..1e80f73 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 4d98f00..b806d91 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;
@@ -180,10 +180,13 @@ namespace OpenSim.Region.Framework.Scenes
180 } 180 }
181 } 181 }
182 182
183 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
184
183 /// <summary> 185 /// <summary>
184 /// Closes a child agent on a given region 186 /// This Closes child agents on neighboring regions
187 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
185 /// </summary> 188 /// </summary>
186 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 189 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
187 { 190 {
188 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 191 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
189 192
@@ -192,31 +195,29 @@ namespace OpenSim.Region.Framework.Scenes
192 Utils.LongToUInts(regionHandle, out x, out y); 195 Utils.LongToUInts(regionHandle, out x, out y);
193 196
194 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 197 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
198 m_scene.SimulationService.CloseChildAgent(destination, agentID);
199 }
195 200
196 m_log.DebugFormat( 201 private void SendCloseChildAgentCompleted(IAsyncResult iar)
197 "[INTERGRID]: Sending close agent {0} to region at {1}-{2}", 202 {
198 agentID, destination.RegionCoordX, destination.RegionCoordY); 203 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
199 204 icon.EndInvoke(iar);
200 m_scene.SimulationService.CloseAgent(destination, agentID);
201 } 205 }
202 206
203 /// <summary>
204 /// Closes a child agents in a collection of regions. Does so asynchronously
205 /// so that the caller doesn't wait.
206 /// </summary>
207 /// <param name="agentID"></param>
208 /// <param name="regionslst"></param>
209 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 207 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
210 { 208 {
211 foreach (ulong handle in regionslst) 209 foreach (ulong handle in regionslst)
212 { 210 {
213 SendCloseChildAgent(agentID, handle); 211 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
212 d.BeginInvoke(agentID, handle,
213 SendCloseChildAgentCompleted,
214 d);
214 } 215 }
215 } 216 }
216 217
217 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 218 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
218 { 219 {
219 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 220 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
220 } 221 }
221 } 222 }
222} \ No newline at end of file 223}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index bc3400a..3cd4a10 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
@@ -120,13 +130,18 @@ namespace OpenSim.Region.Framework.Scenes
120 130
121 protected internal void Close() 131 protected internal void Close()
122 { 132 {
123 lock (m_presenceLock) 133 m_scenePresencesLock.EnterWriteLock();
134 try
124 { 135 {
125 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 136 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
126 List<ScenePresence> newlist = new List<ScenePresence>(); 137 List<ScenePresence> newlist = new List<ScenePresence>();
127 m_scenePresenceMap = newmap; 138 m_scenePresenceMap = newmap;
128 m_scenePresenceArray = newlist; 139 m_scenePresenceArray = newlist;
129 } 140 }
141 finally
142 {
143 m_scenePresencesLock.ExitWriteLock();
144 }
130 145
131 lock (SceneObjectGroupsByFullID) 146 lock (SceneObjectGroupsByFullID)
132 SceneObjectGroupsByFullID.Clear(); 147 SceneObjectGroupsByFullID.Clear();
@@ -247,6 +262,33 @@ namespace OpenSim.Region.Framework.Scenes
247 protected internal bool AddRestoredSceneObject( 262 protected internal bool AddRestoredSceneObject(
248 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 263 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
249 { 264 {
265 if (!m_parentScene.CombineRegions)
266 {
267 // KF: Check for out-of-region, move inside and make static.
268 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
269 sceneObject.RootPart.GroupPosition.Y,
270 sceneObject.RootPart.GroupPosition.Z);
271 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 ||
272 npos.X > Constants.RegionSize ||
273 npos.Y > Constants.RegionSize))
274 {
275 if (npos.X < 0.0) npos.X = 1.0f;
276 if (npos.Y < 0.0) npos.Y = 1.0f;
277 if (npos.Z < 0.0) npos.Z = 0.0f;
278 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
279 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
280
281 foreach (SceneObjectPart part in sceneObject.Parts)
282 {
283 part.GroupPosition = npos;
284 }
285 sceneObject.RootPart.Velocity = Vector3.Zero;
286 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
287 sceneObject.RootPart.Acceleration = Vector3.Zero;
288 sceneObject.RootPart.Velocity = Vector3.Zero;
289 }
290 }
291
250 if (attachToBackup && (!alreadyPersisted)) 292 if (attachToBackup && (!alreadyPersisted))
251 { 293 {
252 sceneObject.ForceInventoryPersistence(); 294 sceneObject.ForceInventoryPersistence();
@@ -336,6 +378,11 @@ namespace OpenSim.Region.Framework.Scenes
336 /// </returns> 378 /// </returns>
337 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 379 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
338 { 380 {
381 if (sceneObject == null)
382 {
383 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
384 return false;
385 }
339 if (sceneObject.UUID == UUID.Zero) 386 if (sceneObject.UUID == UUID.Zero)
340 { 387 {
341 m_log.ErrorFormat( 388 m_log.ErrorFormat(
@@ -470,6 +517,30 @@ namespace OpenSim.Region.Framework.Scenes
470 m_updateList[obj.UUID] = obj; 517 m_updateList[obj.UUID] = obj;
471 } 518 }
472 519
520 public void FireAttachToBackup(SceneObjectGroup obj)
521 {
522 if (OnAttachToBackup != null)
523 {
524 OnAttachToBackup(obj);
525 }
526 }
527
528 public void FireDetachFromBackup(SceneObjectGroup obj)
529 {
530 if (OnDetachFromBackup != null)
531 {
532 OnDetachFromBackup(obj);
533 }
534 }
535
536 public void FireChangeBackup(SceneObjectGroup obj)
537 {
538 if (OnChangeBackup != null)
539 {
540 OnChangeBackup(obj);
541 }
542 }
543
473 /// <summary> 544 /// <summary>
474 /// Process all pending updates 545 /// Process all pending updates
475 /// </summary> 546 /// </summary>
@@ -587,7 +658,8 @@ namespace OpenSim.Region.Framework.Scenes
587 658
588 Entities[presence.UUID] = presence; 659 Entities[presence.UUID] = presence;
589 660
590 lock (m_presenceLock) 661 m_scenePresencesLock.EnterWriteLock();
662 try
591 { 663 {
592 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 664 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
593 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 665 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -611,6 +683,10 @@ namespace OpenSim.Region.Framework.Scenes
611 m_scenePresenceMap = newmap; 683 m_scenePresenceMap = newmap;
612 m_scenePresenceArray = newlist; 684 m_scenePresenceArray = newlist;
613 } 685 }
686 finally
687 {
688 m_scenePresencesLock.ExitWriteLock();
689 }
614 } 690 }
615 691
616 /// <summary> 692 /// <summary>
@@ -625,7 +701,8 @@ namespace OpenSim.Region.Framework.Scenes
625 agentID); 701 agentID);
626 } 702 }
627 703
628 lock (m_presenceLock) 704 m_scenePresencesLock.EnterWriteLock();
705 try
629 { 706 {
630 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 707 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
631 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 708 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -647,6 +724,10 @@ namespace OpenSim.Region.Framework.Scenes
647 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 724 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
648 } 725 }
649 } 726 }
727 finally
728 {
729 m_scenePresencesLock.ExitWriteLock();
730 }
650 } 731 }
651 732
652 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 733 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1362,8 +1443,13 @@ namespace OpenSim.Region.Framework.Scenes
1362 { 1443 {
1363 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1444 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1364 { 1445 {
1365 if (m_parentScene.AttachmentsModule != null) 1446 // Set the new attachment point data in the object
1366 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1447 byte attachmentPoint = group.GetAttachmentPoint();
1448 group.UpdateGroupPosition(pos);
1449 group.IsAttachment = false;
1450 group.AbsolutePosition = group.RootPart.AttachedPos;
1451 group.AttachmentPoint = attachmentPoint;
1452 group.HasGroupChanged = true;
1367 } 1453 }
1368 else 1454 else
1369 { 1455 {
@@ -1627,6 +1713,12 @@ namespace OpenSim.Region.Framework.Scenes
1627 /// <param name="childPrims"></param> 1713 /// <param name="childPrims"></param>
1628 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1714 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1629 { 1715 {
1716 if (root.KeyframeMotion != null)
1717 {
1718 root.KeyframeMotion.Stop();
1719 root.KeyframeMotion = null;
1720 }
1721
1630 SceneObjectGroup parentGroup = root.ParentGroup; 1722 SceneObjectGroup parentGroup = root.ParentGroup;
1631 if (parentGroup == null) return; 1723 if (parentGroup == null) return;
1632 1724
@@ -1635,8 +1727,11 @@ namespace OpenSim.Region.Framework.Scenes
1635 return; 1727 return;
1636 1728
1637 Monitor.Enter(m_updateLock); 1729 Monitor.Enter(m_updateLock);
1730
1638 try 1731 try
1639 { 1732 {
1733 parentGroup.areUpdatesSuspended = true;
1734
1640 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1735 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1641 1736
1642 // We do this in reverse to get the link order of the prims correct 1737 // We do this in reverse to get the link order of the prims correct
@@ -1651,9 +1746,13 @@ namespace OpenSim.Region.Framework.Scenes
1651 // Make sure no child prim is set for sale 1746 // Make sure no child prim is set for sale
1652 // So that, on delink, no prims are unwittingly 1747 // So that, on delink, no prims are unwittingly
1653 // left for sale and sold off 1748 // left for sale and sold off
1654 child.RootPart.ObjectSaleType = 0; 1749
1655 child.RootPart.SalePrice = 10; 1750 if (child != null)
1656 childGroups.Add(child); 1751 {
1752 child.RootPart.ObjectSaleType = 0;
1753 child.RootPart.SalePrice = 10;
1754 childGroups.Add(child);
1755 }
1657 } 1756 }
1658 1757
1659 foreach (SceneObjectGroup child in childGroups) 1758 foreach (SceneObjectGroup child in childGroups)
@@ -1680,6 +1779,16 @@ namespace OpenSim.Region.Framework.Scenes
1680 } 1779 }
1681 finally 1780 finally
1682 { 1781 {
1782 lock (SceneObjectGroupsByLocalPartID)
1783 {
1784 foreach (SceneObjectPart part in parentGroup.Parts)
1785 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1786 }
1787
1788 parentGroup.areUpdatesSuspended = false;
1789 parentGroup.HasGroupChanged = true;
1790 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1791 parentGroup.ScheduleGroupForFullUpdate();
1683 Monitor.Exit(m_updateLock); 1792 Monitor.Exit(m_updateLock);
1684 } 1793 }
1685 } 1794 }
@@ -1702,6 +1811,11 @@ namespace OpenSim.Region.Framework.Scenes
1702 { 1811 {
1703 if (part != null) 1812 if (part != null)
1704 { 1813 {
1814 if (part.KeyframeMotion != null)
1815 {
1816 part.KeyframeMotion.Stop();
1817 part.KeyframeMotion = null;
1818 }
1705 if (part.ParentGroup.PrimCount != 1) // Skip single 1819 if (part.ParentGroup.PrimCount != 1) // Skip single
1706 { 1820 {
1707 if (part.LinkNum < 2) // Root 1821 if (part.LinkNum < 2) // Root
@@ -1716,21 +1830,24 @@ namespace OpenSim.Region.Framework.Scenes
1716 1830
1717 SceneObjectGroup group = part.ParentGroup; 1831 SceneObjectGroup group = part.ParentGroup;
1718 if (!affectedGroups.Contains(group)) 1832 if (!affectedGroups.Contains(group))
1833 {
1834 group.areUpdatesSuspended = true;
1719 affectedGroups.Add(group); 1835 affectedGroups.Add(group);
1836 }
1720 } 1837 }
1721 } 1838 }
1722 } 1839 }
1723 1840
1724 foreach (SceneObjectPart child in childParts) 1841 if (childParts.Count > 0)
1725 { 1842 {
1726 // Unlink all child parts from their groups 1843 foreach (SceneObjectPart child in childParts)
1727 // 1844 {
1728 child.ParentGroup.DelinkFromGroup(child, true); 1845 // Unlink all child parts from their groups
1729 1846 //
1730 // These are not in affected groups and will not be 1847 child.ParentGroup.DelinkFromGroup(child, true);
1731 // handled further. Do the honors here. 1848 child.ParentGroup.HasGroupChanged = true;
1732 child.ParentGroup.HasGroupChanged = true; 1849 child.ParentGroup.ScheduleGroupForFullUpdate();
1733 child.ParentGroup.ScheduleGroupForFullUpdate(); 1850 }
1734 } 1851 }
1735 1852
1736 foreach (SceneObjectPart root in rootParts) 1853 foreach (SceneObjectPart root in rootParts)
@@ -1740,56 +1857,68 @@ namespace OpenSim.Region.Framework.Scenes
1740 // However, editing linked parts and unlinking may be different 1857 // However, editing linked parts and unlinking may be different
1741 // 1858 //
1742 SceneObjectGroup group = root.ParentGroup; 1859 SceneObjectGroup group = root.ParentGroup;
1860 group.areUpdatesSuspended = true;
1743 1861
1744 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1862 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1745 int numChildren = newSet.Count; 1863 int numChildren = newSet.Count;
1746 1864
1865 if (numChildren == 1)
1866 break;
1867
1747 // If there are prims left in a link set, but the root is 1868 // If there are prims left in a link set, but the root is
1748 // slated for unlink, we need to do this 1869 // slated for unlink, we need to do this
1870 // Unlink the remaining set
1749 // 1871 //
1750 if (numChildren != 1) 1872 bool sendEventsToRemainder = true;
1751 { 1873 if (numChildren > 1)
1752 // Unlink the remaining set 1874 sendEventsToRemainder = false;
1753 //
1754 bool sendEventsToRemainder = true;
1755 if (numChildren > 1)
1756 sendEventsToRemainder = false;
1757 1875
1758 foreach (SceneObjectPart p in newSet) 1876 foreach (SceneObjectPart p in newSet)
1877 {
1878 if (p != group.RootPart)
1759 { 1879 {
1760 if (p != group.RootPart) 1880 group.DelinkFromGroup(p, sendEventsToRemainder);
1761 group.DelinkFromGroup(p, sendEventsToRemainder); 1881 if (numChildren > 2)
1882 {
1883 p.ParentGroup.areUpdatesSuspended = true;
1884 }
1885 else
1886 {
1887 p.ParentGroup.HasGroupChanged = true;
1888 p.ParentGroup.ScheduleGroupForFullUpdate();
1889 }
1762 } 1890 }
1891 }
1892
1893 // If there is more than one prim remaining, we
1894 // need to re-link
1895 //
1896 if (numChildren > 2)
1897 {
1898 // Remove old root
1899 //
1900 if (newSet.Contains(root))
1901 newSet.Remove(root);
1763 1902
1764 // If there is more than one prim remaining, we 1903 // Preserve link ordering
1765 // need to re-link
1766 // 1904 //
1767 if (numChildren > 2) 1905 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1768 { 1906 {
1769 // Remove old root 1907 return a.LinkNum.CompareTo(b.LinkNum);
1770 // 1908 });
1771 if (newSet.Contains(root))
1772 newSet.Remove(root);
1773
1774 // Preserve link ordering
1775 //
1776 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1777 {
1778 return a.LinkNum.CompareTo(b.LinkNum);
1779 });
1780 1909
1781 // Determine new root 1910 // Determine new root
1782 // 1911 //
1783 SceneObjectPart newRoot = newSet[0]; 1912 SceneObjectPart newRoot = newSet[0];
1784 newSet.RemoveAt(0); 1913 newSet.RemoveAt(0);
1785 1914
1786 foreach (SceneObjectPart newChild in newSet) 1915 foreach (SceneObjectPart newChild in newSet)
1787 newChild.ClearUpdateSchedule(); 1916 newChild.ClearUpdateSchedule();
1788 1917
1789 LinkObjects(newRoot, newSet); 1918 newRoot.ParentGroup.areUpdatesSuspended = true;
1790 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1919 LinkObjects(newRoot, newSet);
1791 affectedGroups.Add(newRoot.ParentGroup); 1920 if (!affectedGroups.Contains(newRoot.ParentGroup))
1792 } 1921 affectedGroups.Add(newRoot.ParentGroup);
1793 } 1922 }
1794 } 1923 }
1795 1924
@@ -1797,8 +1926,14 @@ namespace OpenSim.Region.Framework.Scenes
1797 // 1926 //
1798 foreach (SceneObjectGroup g in affectedGroups) 1927 foreach (SceneObjectGroup g in affectedGroups)
1799 { 1928 {
1929 // Child prims that have been unlinked and deleted will
1930 // return unless the root is deleted. This will remove them
1931 // from the database. They will be rewritten immediately,
1932 // minus the rows for the unlinked child prims.
1933 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1800 g.TriggerScriptChangedEvent(Changed.LINK); 1934 g.TriggerScriptChangedEvent(Changed.LINK);
1801 g.HasGroupChanged = true; // Persist 1935 g.HasGroupChanged = true; // Persist
1936 g.areUpdatesSuspended = false;
1802 g.ScheduleGroupForFullUpdate(); 1937 g.ScheduleGroupForFullUpdate();
1803 } 1938 }
1804 } 1939 }
@@ -1900,9 +2035,6 @@ namespace OpenSim.Region.Framework.Scenes
1900 child.ApplyNextOwnerPermissions(); 2035 child.ApplyNextOwnerPermissions();
1901 } 2036 }
1902 } 2037 }
1903
1904 copy.RootPart.ObjectSaleType = 0;
1905 copy.RootPart.SalePrice = 10;
1906 } 2038 }
1907 2039
1908 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2040 // 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 a73d9b6..f3660a5 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 878476e..2d71372 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 }
@@ -247,10 +311,10 @@ namespace OpenSim.Region.Framework.Scenes
247 311
248 private bool m_scriptListens_atTarget; 312 private bool m_scriptListens_atTarget;
249 private bool m_scriptListens_notAtTarget; 313 private bool m_scriptListens_notAtTarget;
250
251 private bool m_scriptListens_atRotTarget; 314 private bool m_scriptListens_atRotTarget;
252 private bool m_scriptListens_notAtRotTarget; 315 private bool m_scriptListens_notAtRotTarget;
253 316
317 public bool m_dupeInProgress = false;
254 internal Dictionary<UUID, string> m_savedScriptState; 318 internal Dictionary<UUID, string> m_savedScriptState;
255 319
256 #region Properties 320 #region Properties
@@ -287,6 +351,16 @@ namespace OpenSim.Region.Framework.Scenes
287 get { return m_parts.Count; } 351 get { return m_parts.Count; }
288 } 352 }
289 353
354// protected Quaternion m_rotation = Quaternion.Identity;
355//
356// public virtual Quaternion Rotation
357// {
358// get { return m_rotation; }
359// set {
360// m_rotation = value;
361// }
362// }
363
290 public Quaternion GroupRotation 364 public Quaternion GroupRotation
291 { 365 {
292 get { return m_rootPart.RotationOffset; } 366 get { return m_rootPart.RotationOffset; }
@@ -388,14 +462,99 @@ namespace OpenSim.Region.Framework.Scenes
388 462
389 if (Scene != null) 463 if (Scene != null)
390 { 464 {
391 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 465 // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
392 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 466 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
467 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
468 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W)
469 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S))
393 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 470 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
394 { 471 {
395 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 472 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
473 uint x = 0;
474 uint y = 0;
475 string version = String.Empty;
476 Vector3 newpos = Vector3.Zero;
477 OpenSim.Services.Interfaces.GridRegion destination = null;
478
479 bool canCross = true;
480 foreach (ScenePresence av in m_linkedAvatars)
481 {
482 // We need to cross these agents. First, let's find
483 // out if any of them can't cross for some reason.
484 // We have to deny the crossing entirely if any
485 // of them are banned. Alternatively, we could
486 // unsit banned agents....
487
488
489 // We set the avatar position as being the object
490 // position to get the region to send to
491 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
492 {
493 canCross = false;
494 break;
495 }
496
497 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
498 }
499
500 if (canCross)
501 {
502 // We unparent the SP quietly so that it won't
503 // be made to stand up
504 foreach (ScenePresence av in m_linkedAvatars)
505 {
506 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
507 if (parentPart != null)
508 av.ParentUUID = parentPart.UUID;
509
510 av.ParentID = 0;
511 }
512
513 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
514
515 // Normalize
516 if (val.X >= Constants.RegionSize)
517 val.X -= Constants.RegionSize;
518 if (val.Y >= Constants.RegionSize)
519 val.Y -= Constants.RegionSize;
520 if (val.X < 0)
521 val.X += Constants.RegionSize;
522 if (val.Y < 0)
523 val.Y += Constants.RegionSize;
524
525 // If it's deleted, crossing was successful
526 if (IsDeleted)
527 {
528 foreach (ScenePresence av in m_linkedAvatars)
529 {
530 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
531
532 av.IsInTransit = true;
533
534 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
535 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
536 }
537
538 return;
539 }
540 }
541 else if (RootPart.PhysActor != null)
542 {
543 RootPart.PhysActor.CrossingFailure();
544 }
545
546 Vector3 oldp = AbsolutePosition;
547 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
548 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
549 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
396 } 550 }
397 } 551 }
398 552/* don't see the need but worse don't see where is restored to false if things stay in
553 foreach (SceneObjectPart part in m_parts.GetArray())
554 {
555 part.IgnoreUndoUpdate = true;
556 }
557 */
399 if (RootPart.GetStatusSandbox()) 558 if (RootPart.GetStatusSandbox())
400 { 559 {
401 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 560 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -409,10 +568,30 @@ namespace OpenSim.Region.Framework.Scenes
409 return; 568 return;
410 } 569 }
411 } 570 }
412
413 SceneObjectPart[] parts = m_parts.GetArray(); 571 SceneObjectPart[] parts = m_parts.GetArray();
414 for (int i = 0; i < parts.Length; i++) 572 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
415 parts[i].GroupPosition = val; 573 if (m_dupeInProgress)
574 triggerScriptEvent = false;
575 foreach (SceneObjectPart part in parts)
576 {
577 part.GroupPosition = val;
578 if (triggerScriptEvent)
579 part.TriggerScriptChangedEvent(Changed.POSITION);
580 }
581 if (!m_dupeInProgress)
582 {
583 foreach (ScenePresence av in m_linkedAvatars)
584 {
585 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
586 if (p != null && m_parts.TryGetValue(p.UUID, out p))
587 {
588 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
589 av.AbsolutePosition += offset;
590 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
591 av.SendAvatarDataToAllAgents();
592 }
593 }
594 }
416 595
417 //if (m_rootPart.PhysActor != null) 596 //if (m_rootPart.PhysActor != null)
418 //{ 597 //{
@@ -427,6 +606,29 @@ namespace OpenSim.Region.Framework.Scenes
427 } 606 }
428 } 607 }
429 608
609 public override Vector3 Velocity
610 {
611 get { return RootPart.Velocity; }
612 set { RootPart.Velocity = value; }
613 }
614
615 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
616 {
617 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
618 ScenePresence agent = icon.EndInvoke(iar);
619
620 //// If the cross was successful, this agent is a child agent
621 //if (agent.IsChildAgent)
622 // agent.Reset();
623 //else // Not successful
624 // agent.RestoreInCurrentScene();
625
626 // In any case
627 agent.IsInTransit = false;
628
629 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
630 }
631
430 public override uint LocalId 632 public override uint LocalId
431 { 633 {
432 get { return m_rootPart.LocalId; } 634 get { return m_rootPart.LocalId; }
@@ -519,6 +721,8 @@ namespace OpenSim.Region.Framework.Scenes
519 child.PhysActor.Selected = value; 721 child.PhysActor.Selected = value;
520 } 722 }
521 } 723 }
724 if (RootPart.KeyframeMotion != null)
725 RootPart.KeyframeMotion.Selected = value;
522 } 726 }
523 } 727 }
524 728
@@ -578,6 +782,7 @@ namespace OpenSim.Region.Framework.Scenes
578 /// </summary> 782 /// </summary>
579 public SceneObjectGroup() 783 public SceneObjectGroup()
580 { 784 {
785
581 } 786 }
582 787
583 /// <summary> 788 /// <summary>
@@ -594,7 +799,7 @@ namespace OpenSim.Region.Framework.Scenes
594 /// Constructor. This object is added to the scene later via AttachToScene() 799 /// Constructor. This object is added to the scene later via AttachToScene()
595 /// </summary> 800 /// </summary>
596 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 801 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
597 { 802 {
598 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 803 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
599 } 804 }
600 805
@@ -642,6 +847,9 @@ namespace OpenSim.Region.Framework.Scenes
642 /// </summary> 847 /// </summary>
643 public virtual void AttachToBackup() 848 public virtual void AttachToBackup()
644 { 849 {
850 if (IsAttachment) return;
851 m_scene.SceneGraph.FireAttachToBackup(this);
852
645 if (InSceneBackup) 853 if (InSceneBackup)
646 { 854 {
647 //m_log.DebugFormat( 855 //m_log.DebugFormat(
@@ -684,6 +892,13 @@ namespace OpenSim.Region.Framework.Scenes
684 892
685 ApplyPhysics(); 893 ApplyPhysics();
686 894
895 if (RootPart.PhysActor != null)
896 RootPart.Force = RootPart.Force;
897 if (RootPart.PhysActor != null)
898 RootPart.Torque = RootPart.Torque;
899 if (RootPart.PhysActor != null)
900 RootPart.Buoyancy = RootPart.Buoyancy;
901
687 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 902 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
688 // for the same object with very different properties. The caller must schedule the update. 903 // for the same object with very different properties. The caller must schedule the update.
689 //ScheduleGroupForFullUpdate(); 904 //ScheduleGroupForFullUpdate();
@@ -699,6 +914,10 @@ namespace OpenSim.Region.Framework.Scenes
699 EntityIntersection result = new EntityIntersection(); 914 EntityIntersection result = new EntityIntersection();
700 915
701 SceneObjectPart[] parts = m_parts.GetArray(); 916 SceneObjectPart[] parts = m_parts.GetArray();
917
918 // Find closest hit here
919 float idist = float.MaxValue;
920
702 for (int i = 0; i < parts.Length; i++) 921 for (int i = 0; i < parts.Length; i++)
703 { 922 {
704 SceneObjectPart part = parts[i]; 923 SceneObjectPart part = parts[i];
@@ -713,11 +932,6 @@ namespace OpenSim.Region.Framework.Scenes
713 932
714 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 933 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
715 934
716 // This may need to be updated to the maximum draw distance possible..
717 // We might (and probably will) be checking for prim creation from other sims
718 // when the camera crosses the border.
719 float idist = Constants.RegionSize;
720
721 if (inter.HitTF) 935 if (inter.HitTF)
722 { 936 {
723 // We need to find the closest prim to return to the testcaller along the ray 937 // We need to find the closest prim to return to the testcaller along the ray
@@ -728,10 +942,11 @@ namespace OpenSim.Region.Framework.Scenes
728 result.obj = part; 942 result.obj = part;
729 result.normal = inter.normal; 943 result.normal = inter.normal;
730 result.distance = inter.distance; 944 result.distance = inter.distance;
945
946 idist = inter.distance;
731 } 947 }
732 } 948 }
733 } 949 }
734
735 return result; 950 return result;
736 } 951 }
737 952
@@ -743,25 +958,27 @@ namespace OpenSim.Region.Framework.Scenes
743 /// <returns></returns> 958 /// <returns></returns>
744 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 959 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
745 { 960 {
746 maxX = -256f; 961 maxX = float.MinValue;
747 maxY = -256f; 962 maxY = float.MinValue;
748 maxZ = -256f; 963 maxZ = float.MinValue;
749 minX = 256f; 964 minX = float.MaxValue;
750 minY = 256f; 965 minY = float.MaxValue;
751 minZ = 8192f; 966 minZ = float.MaxValue;
752 967
753 SceneObjectPart[] parts = m_parts.GetArray(); 968 SceneObjectPart[] parts = m_parts.GetArray();
754 for (int i = 0; i < parts.Length; i++) 969 foreach (SceneObjectPart part in parts)
755 { 970 {
756 SceneObjectPart part = parts[i];
757
758 Vector3 worldPos = part.GetWorldPosition(); 971 Vector3 worldPos = part.GetWorldPosition();
759 Vector3 offset = worldPos - AbsolutePosition; 972 Vector3 offset = worldPos - AbsolutePosition;
760 Quaternion worldRot; 973 Quaternion worldRot;
761 if (part.ParentID == 0) 974 if (part.ParentID == 0)
975 {
762 worldRot = part.RotationOffset; 976 worldRot = part.RotationOffset;
977 }
763 else 978 else
979 {
764 worldRot = part.GetWorldRotation(); 980 worldRot = part.GetWorldRotation();
981 }
765 982
766 Vector3 frontTopLeft; 983 Vector3 frontTopLeft;
767 Vector3 frontTopRight; 984 Vector3 frontTopRight;
@@ -773,6 +990,8 @@ namespace OpenSim.Region.Framework.Scenes
773 Vector3 backBottomLeft; 990 Vector3 backBottomLeft;
774 Vector3 backBottomRight; 991 Vector3 backBottomRight;
775 992
993 // Vector3[] corners = new Vector3[8];
994
776 Vector3 orig = Vector3.Zero; 995 Vector3 orig = Vector3.Zero;
777 996
778 frontTopLeft.X = orig.X - (part.Scale.X / 2); 997 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -807,6 +1026,38 @@ namespace OpenSim.Region.Framework.Scenes
807 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1026 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
808 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1027 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
809 1028
1029
1030
1031 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1032 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1033 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1034 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1035 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1036 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1037 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1038 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1039
1040 //for (int i = 0; i < 8; i++)
1041 //{
1042 // corners[i] = corners[i] * worldRot;
1043 // corners[i] += offset;
1044
1045 // if (corners[i].X > maxX)
1046 // maxX = corners[i].X;
1047 // if (corners[i].X < minX)
1048 // minX = corners[i].X;
1049
1050 // if (corners[i].Y > maxY)
1051 // maxY = corners[i].Y;
1052 // if (corners[i].Y < minY)
1053 // minY = corners[i].Y;
1054
1055 // if (corners[i].Z > maxZ)
1056 // maxZ = corners[i].Y;
1057 // if (corners[i].Z < minZ)
1058 // minZ = corners[i].Z;
1059 //}
1060
810 frontTopLeft = frontTopLeft * worldRot; 1061 frontTopLeft = frontTopLeft * worldRot;
811 frontTopRight = frontTopRight * worldRot; 1062 frontTopRight = frontTopRight * worldRot;
812 frontBottomLeft = frontBottomLeft * worldRot; 1063 frontBottomLeft = frontBottomLeft * worldRot;
@@ -828,6 +1079,15 @@ namespace OpenSim.Region.Framework.Scenes
828 backTopLeft += offset; 1079 backTopLeft += offset;
829 backTopRight += offset; 1080 backTopRight += offset;
830 1081
1082 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1083 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1084 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1085 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1086 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1087 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1088 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1089 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1090
831 if (frontTopRight.X > maxX) 1091 if (frontTopRight.X > maxX)
832 maxX = frontTopRight.X; 1092 maxX = frontTopRight.X;
833 if (frontTopLeft.X > maxX) 1093 if (frontTopLeft.X > maxX)
@@ -973,15 +1233,20 @@ namespace OpenSim.Region.Framework.Scenes
973 1233
974 public void SaveScriptedState(XmlTextWriter writer) 1234 public void SaveScriptedState(XmlTextWriter writer)
975 { 1235 {
1236 SaveScriptedState(writer, false);
1237 }
1238
1239 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1240 {
976 XmlDocument doc = new XmlDocument(); 1241 XmlDocument doc = new XmlDocument();
977 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1242 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
978 1243
979 SceneObjectPart[] parts = m_parts.GetArray(); 1244 SceneObjectPart[] parts = m_parts.GetArray();
980 for (int i = 0; i < parts.Length; i++) 1245 for (int i = 0; i < parts.Length; i++)
981 { 1246 {
982 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1247 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
983 foreach (KeyValuePair<UUID, string> kvp in pstates) 1248 foreach (KeyValuePair<UUID, string> kvp in pstates)
984 states.Add(kvp.Key, kvp.Value); 1249 states[kvp.Key] = kvp.Value;
985 } 1250 }
986 1251
987 if (states.Count > 0) 1252 if (states.Count > 0)
@@ -1001,6 +1266,169 @@ namespace OpenSim.Region.Framework.Scenes
1001 } 1266 }
1002 1267
1003 /// <summary> 1268 /// <summary>
1269 /// Add the avatar to this linkset (avatar is sat).
1270 /// </summary>
1271 /// <param name="agentID"></param>
1272 public void AddAvatar(UUID agentID)
1273 {
1274 ScenePresence presence;
1275 if (m_scene.TryGetScenePresence(agentID, out presence))
1276 {
1277 if (!m_linkedAvatars.Contains(presence))
1278 {
1279 m_linkedAvatars.Add(presence);
1280 }
1281 }
1282 }
1283
1284 /// <summary>
1285 /// Delete the avatar from this linkset (avatar is unsat).
1286 /// </summary>
1287 /// <param name="agentID"></param>
1288 public void DeleteAvatar(UUID agentID)
1289 {
1290 ScenePresence presence;
1291 if (m_scene.TryGetScenePresence(agentID, out presence))
1292 {
1293 if (m_linkedAvatars.Contains(presence))
1294 {
1295 m_linkedAvatars.Remove(presence);
1296 }
1297 }
1298 }
1299
1300 /// <summary>
1301 /// Returns the list of linked presences (avatars sat on this group)
1302 /// </summary>
1303 /// <param name="agentID"></param>
1304 public List<ScenePresence> GetLinkedAvatars()
1305 {
1306 return m_linkedAvatars;
1307 }
1308
1309 /// <summary>
1310 /// Attach this scene object to the given avatar.
1311 /// </summary>
1312 /// <param name="agentID"></param>
1313 /// <param name="attachmentpoint"></param>
1314 /// <param name="AttachOffset"></param>
1315 private void AttachToAgent(
1316 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1317 {
1318 if (avatar != null)
1319 {
1320 // don't attach attachments to child agents
1321 if (avatar.IsChildAgent) return;
1322
1323 // Remove from database and parcel prim count
1324 m_scene.DeleteFromStorage(so.UUID);
1325 m_scene.EventManager.TriggerParcelPrimCountTainted();
1326
1327 so.AttachedAvatar = avatar.UUID;
1328
1329 if (so.RootPart.PhysActor != null)
1330 {
1331 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1332 so.RootPart.PhysActor = null;
1333 }
1334
1335 so.AbsolutePosition = attachOffset;
1336 so.RootPart.AttachedPos = attachOffset;
1337 so.IsAttachment = true;
1338 so.RootPart.SetParentLocalId(avatar.LocalId);
1339 so.AttachmentPoint = attachmentpoint;
1340
1341 avatar.AddAttachment(this);
1342
1343 if (!silent)
1344 {
1345 // Killing it here will cause the client to deselect it
1346 // It then reappears on the avatar, deselected
1347 // through the full update below
1348 //
1349 if (IsSelected)
1350 {
1351 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1352 }
1353
1354 IsSelected = false; // fudge....
1355 ScheduleGroupForFullUpdate();
1356 }
1357 }
1358 else
1359 {
1360 m_log.WarnFormat(
1361 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1362 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1363 }
1364 }
1365
1366 public byte GetAttachmentPoint()
1367 {
1368 return m_rootPart.Shape.State;
1369 }
1370
1371 public void DetachToGround()
1372 {
1373 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1374 if (avatar == null)
1375 return;
1376
1377 avatar.RemoveAttachment(this);
1378
1379 Vector3 detachedpos = new Vector3(127f,127f,127f);
1380 if (avatar == null)
1381 return;
1382
1383 detachedpos = avatar.AbsolutePosition;
1384 RootPart.FromItemID = UUID.Zero;
1385
1386 AbsolutePosition = detachedpos;
1387 AttachedAvatar = UUID.Zero;
1388
1389 //SceneObjectPart[] parts = m_parts.GetArray();
1390 //for (int i = 0; i < parts.Length; i++)
1391 // parts[i].AttachedAvatar = UUID.Zero;
1392
1393 m_rootPart.SetParentLocalId(0);
1394 AttachmentPoint = (byte)0;
1395 // must check if buildind should be true or false here
1396 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1397 HasGroupChanged = true;
1398 RootPart.Rezzed = DateTime.Now;
1399 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1400 AttachToBackup();
1401 m_scene.EventManager.TriggerParcelPrimCountTainted();
1402 m_rootPart.ScheduleFullUpdate();
1403 m_rootPart.ClearUndoState();
1404 }
1405
1406 public void DetachToInventoryPrep()
1407 {
1408 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1409 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1410 if (avatar != null)
1411 {
1412 //detachedpos = avatar.AbsolutePosition;
1413 avatar.RemoveAttachment(this);
1414 }
1415
1416 AttachedAvatar = UUID.Zero;
1417
1418 /*SceneObjectPart[] parts = m_parts.GetArray();
1419 for (int i = 0; i < parts.Length; i++)
1420 parts[i].AttachedAvatar = UUID.Zero;*/
1421
1422 m_rootPart.SetParentLocalId(0);
1423 //m_rootPart.SetAttachmentPoint((byte)0);
1424 IsAttachment = false;
1425 AbsolutePosition = m_rootPart.AttachedPos;
1426 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1427 //AttachToBackup();
1428 //m_rootPart.ScheduleFullUpdate();
1429 }
1430
1431 /// <summary>
1004 /// 1432 ///
1005 /// </summary> 1433 /// </summary>
1006 /// <param name="part"></param> 1434 /// <param name="part"></param>
@@ -1050,7 +1478,10 @@ namespace OpenSim.Region.Framework.Scenes
1050 public void AddPart(SceneObjectPart part) 1478 public void AddPart(SceneObjectPart part)
1051 { 1479 {
1052 part.SetParent(this); 1480 part.SetParent(this);
1053 part.LinkNum = m_parts.Add(part.UUID, part); 1481 m_parts.Add(part.UUID, part);
1482
1483 part.LinkNum = m_parts.Count;
1484
1054 if (part.LinkNum == 2) 1485 if (part.LinkNum == 2)
1055 RootPart.LinkNum = 1; 1486 RootPart.LinkNum = 1;
1056 } 1487 }
@@ -1138,7 +1569,7 @@ namespace OpenSim.Region.Framework.Scenes
1138// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1569// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1139// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1570// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1140 1571
1141 part.StoreUndoState(); 1572// part.StoreUndoState();
1142 part.OnGrab(offsetPos, remoteClient); 1573 part.OnGrab(offsetPos, remoteClient);
1143 } 1574 }
1144 1575
@@ -1158,6 +1589,11 @@ namespace OpenSim.Region.Framework.Scenes
1158 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1589 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1159 public void DeleteGroupFromScene(bool silent) 1590 public void DeleteGroupFromScene(bool silent)
1160 { 1591 {
1592 // We need to keep track of this state in case this group is still queued for backup.
1593 IsDeleted = true;
1594
1595 DetachFromBackup();
1596
1161 SceneObjectPart[] parts = m_parts.GetArray(); 1597 SceneObjectPart[] parts = m_parts.GetArray();
1162 for (int i = 0; i < parts.Length; i++) 1598 for (int i = 0; i < parts.Length; i++)
1163 { 1599 {
@@ -1180,6 +1616,8 @@ namespace OpenSim.Region.Framework.Scenes
1180 } 1616 }
1181 }); 1617 });
1182 } 1618 }
1619
1620
1183 } 1621 }
1184 1622
1185 public void AddScriptLPS(int count) 1623 public void AddScriptLPS(int count)
@@ -1254,28 +1692,43 @@ namespace OpenSim.Region.Framework.Scenes
1254 /// </summary> 1692 /// </summary>
1255 public void ApplyPhysics() 1693 public void ApplyPhysics()
1256 { 1694 {
1257 // Apply physics to the root prim
1258 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1259
1260 // Apply physics to child prims
1261 SceneObjectPart[] parts = m_parts.GetArray(); 1695 SceneObjectPart[] parts = m_parts.GetArray();
1262 if (parts.Length > 1) 1696 if (parts.Length > 1)
1263 { 1697 {
1698 ResetChildPrimPhysicsPositions();
1699
1700 // Apply physics to the root prim
1701 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
1702
1703
1264 for (int i = 0; i < parts.Length; i++) 1704 for (int i = 0; i < parts.Length; i++)
1265 { 1705 {
1266 SceneObjectPart part = parts[i]; 1706 SceneObjectPart part = parts[i];
1267 if (part.LocalId != m_rootPart.LocalId) 1707 if (part.LocalId != m_rootPart.LocalId)
1268 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 1708 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1269 } 1709 }
1270
1271 // Hack to get the physics scene geometries in the right spot 1710 // Hack to get the physics scene geometries in the right spot
1272 ResetChildPrimPhysicsPositions(); 1711// ResetChildPrimPhysicsPositions();
1712 if (m_rootPart.PhysActor != null)
1713 {
1714 m_rootPart.PhysActor.Building = false;
1715 }
1716 }
1717 else
1718 {
1719 // Apply physics to the root prim
1720 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1273 } 1721 }
1274 } 1722 }
1275 1723
1276 public void SetOwnerId(UUID userId) 1724 public void SetOwnerId(UUID userId)
1277 { 1725 {
1278 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1726 ForEachPart(delegate(SceneObjectPart part)
1727 {
1728
1729 part.OwnerID = userId;
1730
1731 });
1279 } 1732 }
1280 1733
1281 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1734 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1307,11 +1760,17 @@ namespace OpenSim.Region.Framework.Scenes
1307 return; 1760 return;
1308 } 1761 }
1309 1762
1763 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1764 return;
1765
1310 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1766 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1311 // any exception propogate upwards. 1767 // any exception propogate upwards.
1312 try 1768 try
1313 { 1769 {
1314 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1770 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1771 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1772 m_scene.LoadingPrims) // Land may not be valid yet
1773
1315 { 1774 {
1316 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1775 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1317 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1776 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1338,6 +1797,7 @@ namespace OpenSim.Region.Framework.Scenes
1338 } 1797 }
1339 } 1798 }
1340 } 1799 }
1800
1341 } 1801 }
1342 1802
1343 if (m_scene.UseBackup && HasGroupChanged) 1803 if (m_scene.UseBackup && HasGroupChanged)
@@ -1345,6 +1805,20 @@ namespace OpenSim.Region.Framework.Scenes
1345 // don't backup while it's selected or you're asking for changes mid stream. 1805 // don't backup while it's selected or you're asking for changes mid stream.
1346 if (isTimeToPersist() || forcedBackup) 1806 if (isTimeToPersist() || forcedBackup)
1347 { 1807 {
1808 if (m_rootPart.PhysActor != null &&
1809 (!m_rootPart.PhysActor.IsPhysical))
1810 {
1811 // Possible ghost prim
1812 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1813 {
1814 foreach (SceneObjectPart part in m_parts.GetArray())
1815 {
1816 // Re-set physics actor positions and
1817 // orientations
1818 part.GroupPosition = m_rootPart.GroupPosition;
1819 }
1820 }
1821 }
1348// m_log.DebugFormat( 1822// m_log.DebugFormat(
1349// "[SCENE]: Storing {0}, {1} in {2}", 1823// "[SCENE]: Storing {0}, {1} in {2}",
1350// Name, UUID, m_scene.RegionInfo.RegionName); 1824// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1362,6 +1836,11 @@ namespace OpenSim.Region.Framework.Scenes
1362 1836
1363 backup_group.ForEachPart(delegate(SceneObjectPart part) 1837 backup_group.ForEachPart(delegate(SceneObjectPart part)
1364 { 1838 {
1839 if (part.KeyframeMotion != null)
1840 {
1841 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
1842 part.KeyframeMotion.UpdateSceneObject(this);
1843 }
1365 part.Inventory.ProcessInventoryBackup(datastore); 1844 part.Inventory.ProcessInventoryBackup(datastore);
1366 }); 1845 });
1367 1846
@@ -1414,6 +1893,7 @@ namespace OpenSim.Region.Framework.Scenes
1414 /// <returns></returns> 1893 /// <returns></returns>
1415 public SceneObjectGroup Copy(bool userExposed) 1894 public SceneObjectGroup Copy(bool userExposed)
1416 { 1895 {
1896 m_dupeInProgress = true;
1417 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1897 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1418 dupe.m_isBackedUp = false; 1898 dupe.m_isBackedUp = false;
1419 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1899 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
@@ -1428,7 +1908,7 @@ namespace OpenSim.Region.Framework.Scenes
1428 // This is only necessary when userExposed is false! 1908 // This is only necessary when userExposed is false!
1429 1909
1430 bool previousAttachmentStatus = dupe.IsAttachment; 1910 bool previousAttachmentStatus = dupe.IsAttachment;
1431 1911
1432 if (!userExposed) 1912 if (!userExposed)
1433 dupe.IsAttachment = true; 1913 dupe.IsAttachment = true;
1434 1914
@@ -1446,11 +1926,11 @@ namespace OpenSim.Region.Framework.Scenes
1446 dupe.m_rootPart.TrimPermissions(); 1926 dupe.m_rootPart.TrimPermissions();
1447 1927
1448 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1928 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1449 1929
1450 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1930 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1451 { 1931 {
1452 return p1.LinkNum.CompareTo(p2.LinkNum); 1932 return p1.LinkNum.CompareTo(p2.LinkNum);
1453 } 1933 }
1454 ); 1934 );
1455 1935
1456 foreach (SceneObjectPart part in partList) 1936 foreach (SceneObjectPart part in partList)
@@ -1470,21 +1950,24 @@ namespace OpenSim.Region.Framework.Scenes
1470 if (part.PhysActor != null && userExposed) 1950 if (part.PhysActor != null && userExposed)
1471 { 1951 {
1472 PrimitiveBaseShape pbs = newPart.Shape; 1952 PrimitiveBaseShape pbs = newPart.Shape;
1473 1953
1474 newPart.PhysActor 1954 newPart.PhysActor
1475 = m_scene.PhysicsScene.AddPrimShape( 1955 = m_scene.PhysicsScene.AddPrimShape(
1476 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1956 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1477 pbs, 1957 pbs,
1478 newPart.AbsolutePosition, 1958 newPart.AbsolutePosition,
1479 newPart.Scale, 1959 newPart.Scale,
1480 newPart.RotationOffset, 1960 //newPart.RotationOffset,
1961 newPart.GetWorldRotation(),
1481 part.PhysActor.IsPhysical, 1962 part.PhysActor.IsPhysical,
1482 newPart.LocalId); 1963 newPart.LocalId);
1483 1964
1484 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1965 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1485 } 1966 }
1486 } 1967 }
1487 1968 if (dupe.m_rootPart.PhysActor != null && userExposed)
1969 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
1970
1488 if (userExposed) 1971 if (userExposed)
1489 { 1972 {
1490 dupe.UpdateParentIDs(); 1973 dupe.UpdateParentIDs();
@@ -1494,6 +1977,7 @@ namespace OpenSim.Region.Framework.Scenes
1494 ScheduleGroupForFullUpdate(); 1977 ScheduleGroupForFullUpdate();
1495 } 1978 }
1496 1979
1980 m_dupeInProgress = false;
1497 return dupe; 1981 return dupe;
1498 } 1982 }
1499 1983
@@ -1505,11 +1989,24 @@ namespace OpenSim.Region.Framework.Scenes
1505 /// <param name="cGroupID"></param> 1989 /// <param name="cGroupID"></param>
1506 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 1990 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1507 { 1991 {
1508 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 1992 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
1993 // give newpart a new local ID lettng old part keep same
1994 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
1995 newpart.LocalId = m_scene.AllocateLocalId();
1996
1997 SetRootPart(newpart);
1998 if (userExposed)
1999 RootPart.Velocity = Vector3.Zero; // In case source is moving
1509 } 2000 }
1510 2001
1511 public void ScriptSetPhysicsStatus(bool usePhysics) 2002 public void ScriptSetPhysicsStatus(bool usePhysics)
1512 { 2003 {
2004 if (usePhysics)
2005 {
2006 if (RootPart.KeyframeMotion != null)
2007 RootPart.KeyframeMotion.Stop();
2008 RootPart.KeyframeMotion = null;
2009 }
1513 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2010 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1514 } 2011 }
1515 2012
@@ -1573,32 +2070,12 @@ namespace OpenSim.Region.Framework.Scenes
1573 } 2070 }
1574 } 2071 }
1575 2072
1576 public void setAngularImpulse(Vector3 impulse)
1577 {
1578 if (RootPart.PhysActor != null)
1579 {
1580 if (!IsAttachment)
1581 {
1582 RootPart.PhysActor.Torque = impulse;
1583 m_scene.PhysicsScene.AddPhysicsActorTaint(RootPart.PhysActor);
1584 }
1585 }
1586 }
1587
1588 public Vector3 GetTorque() 2073 public Vector3 GetTorque()
1589 { 2074 {
1590 if (RootPart.PhysActor != null) 2075 return RootPart.Torque;
1591 {
1592 if (!IsAttachment)
1593 {
1594 Vector3 torque = RootPart.PhysActor.Torque;
1595 return torque;
1596 }
1597 }
1598
1599 return Vector3.Zero;
1600 } 2076 }
1601 2077
2078 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1602 public void moveToTarget(Vector3 target, float tau) 2079 public void moveToTarget(Vector3 target, float tau)
1603 { 2080 {
1604 if (IsAttachment) 2081 if (IsAttachment)
@@ -1626,6 +2103,46 @@ namespace OpenSim.Region.Framework.Scenes
1626 RootPart.PhysActor.PIDActive = false; 2103 RootPart.PhysActor.PIDActive = false;
1627 } 2104 }
1628 2105
2106 public void rotLookAt(Quaternion target, float strength, float damping)
2107 {
2108 SceneObjectPart rootpart = m_rootPart;
2109 if (rootpart != null)
2110 {
2111 if (IsAttachment)
2112 {
2113 /*
2114 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2115 if (avatar != null)
2116 {
2117 Rotate the Av?
2118 } */
2119 }
2120 else
2121 {
2122 if (rootpart.PhysActor != null)
2123 { // APID must be implemented in your physics system for this to function.
2124 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2125 rootpart.PhysActor.APIDStrength = strength;
2126 rootpart.PhysActor.APIDDamping = damping;
2127 rootpart.PhysActor.APIDActive = true;
2128 }
2129 }
2130 }
2131 }
2132
2133 public void stopLookAt()
2134 {
2135 SceneObjectPart rootpart = m_rootPart;
2136 if (rootpart != null)
2137 {
2138 if (rootpart.PhysActor != null)
2139 { // APID must be implemented in your physics system for this to function.
2140 rootpart.PhysActor.APIDActive = false;
2141 }
2142 }
2143
2144 }
2145
1629 /// <summary> 2146 /// <summary>
1630 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2147 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1631 /// </summary> 2148 /// </summary>
@@ -1680,7 +2197,12 @@ namespace OpenSim.Region.Framework.Scenes
1680 /// <param name="cGroupID"></param> 2197 /// <param name="cGroupID"></param>
1681 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2198 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1682 { 2199 {
1683 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2200 // give new ID to the new part, letting old keep original
2201 // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2202 SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2203 newPart.LocalId = m_scene.AllocateLocalId();
2204 newPart.SetParent(this);
2205
1684 AddPart(newPart); 2206 AddPart(newPart);
1685 2207
1686 SetPartAsNonRoot(newPart); 2208 SetPartAsNonRoot(newPart);
@@ -1809,11 +2331,11 @@ namespace OpenSim.Region.Framework.Scenes
1809 /// Immediately send a full update for this scene object. 2331 /// Immediately send a full update for this scene object.
1810 /// </summary> 2332 /// </summary>
1811 public void SendGroupFullUpdate() 2333 public void SendGroupFullUpdate()
1812 { 2334 {
1813 if (IsDeleted) 2335 if (IsDeleted)
1814 return; 2336 return;
1815 2337
1816// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2338// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1817 2339
1818 RootPart.SendFullUpdateToAllClients(); 2340 RootPart.SendFullUpdateToAllClients();
1819 2341
@@ -1957,6 +2479,11 @@ namespace OpenSim.Region.Framework.Scenes
1957 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2479 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1958 public void LinkToGroup(SceneObjectGroup objectGroup) 2480 public void LinkToGroup(SceneObjectGroup objectGroup)
1959 { 2481 {
2482 LinkToGroup(objectGroup, false);
2483 }
2484
2485 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2486 {
1960// m_log.DebugFormat( 2487// m_log.DebugFormat(
1961// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2488// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1962// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2489// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
@@ -1967,6 +2494,11 @@ namespace OpenSim.Region.Framework.Scenes
1967 2494
1968 SceneObjectPart linkPart = objectGroup.m_rootPart; 2495 SceneObjectPart linkPart = objectGroup.m_rootPart;
1969 2496
2497 if (m_rootPart.PhysActor != null)
2498 m_rootPart.PhysActor.Building = true;
2499 if (linkPart.PhysActor != null)
2500 linkPart.PhysActor.Building = true;
2501
1970 Vector3 oldGroupPosition = linkPart.GroupPosition; 2502 Vector3 oldGroupPosition = linkPart.GroupPosition;
1971 Quaternion oldRootRotation = linkPart.RotationOffset; 2503 Quaternion oldRootRotation = linkPart.RotationOffset;
1972 2504
@@ -1990,13 +2522,33 @@ namespace OpenSim.Region.Framework.Scenes
1990 2522
1991 lock (m_parts.SyncRoot) 2523 lock (m_parts.SyncRoot)
1992 { 2524 {
1993 int linkNum = PrimCount + 1; 2525 int linkNum;
2526 if (insert)
2527 {
2528 linkNum = 2;
2529 foreach (SceneObjectPart part in Parts)
2530 {
2531 if (part.LinkNum > 1)
2532 part.LinkNum++;
2533 }
2534 }
2535 else
2536 {
2537 linkNum = PrimCount + 1;
2538 }
1994 2539
1995 m_parts.Add(linkPart.UUID, linkPart); 2540 m_parts.Add(linkPart.UUID, linkPart);
1996 2541
1997 linkPart.SetParent(this); 2542 linkPart.SetParent(this);
1998 linkPart.CreateSelected = true; 2543 linkPart.CreateSelected = true;
1999 2544
2545 // let physics know
2546 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2547 {
2548 linkPart.PhysActor.link(m_rootPart.PhysActor);
2549 this.Scene.PhysicsScene.AddPhysicsActorTaint(linkPart.PhysActor);
2550 }
2551
2000 linkPart.LinkNum = linkNum++; 2552 linkPart.LinkNum = linkNum++;
2001 2553
2002 SceneObjectPart[] ogParts = objectGroup.Parts; 2554 SceneObjectPart[] ogParts = objectGroup.Parts;
@@ -2009,7 +2561,15 @@ namespace OpenSim.Region.Framework.Scenes
2009 { 2561 {
2010 SceneObjectPart part = ogParts[i]; 2562 SceneObjectPart part = ogParts[i];
2011 if (part.UUID != objectGroup.m_rootPart.UUID) 2563 if (part.UUID != objectGroup.m_rootPart.UUID)
2564 {
2012 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2565 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2566 // let physics know
2567 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2568 {
2569 part.PhysActor.link(m_rootPart.PhysActor);
2570 this.Scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2571 }
2572 }
2013 part.ClearUndoState(); 2573 part.ClearUndoState();
2014 } 2574 }
2015 } 2575 }
@@ -2018,7 +2578,7 @@ namespace OpenSim.Region.Framework.Scenes
2018 objectGroup.IsDeleted = true; 2578 objectGroup.IsDeleted = true;
2019 2579
2020 objectGroup.m_parts.Clear(); 2580 objectGroup.m_parts.Clear();
2021 2581
2022 // Can't do this yet since backup still makes use of the root part without any synchronization 2582 // Can't do this yet since backup still makes use of the root part without any synchronization
2023// objectGroup.m_rootPart = null; 2583// objectGroup.m_rootPart = null;
2024 2584
@@ -2029,6 +2589,9 @@ namespace OpenSim.Region.Framework.Scenes
2029 // unmoved prims! 2589 // unmoved prims!
2030 ResetChildPrimPhysicsPositions(); 2590 ResetChildPrimPhysicsPositions();
2031 2591
2592 if (m_rootPart.PhysActor != null)
2593 m_rootPart.PhysActor.Building = false;
2594
2032 //HasGroupChanged = true; 2595 //HasGroupChanged = true;
2033 //ScheduleGroupForFullUpdate(); 2596 //ScheduleGroupForFullUpdate();
2034 } 2597 }
@@ -2081,7 +2644,10 @@ namespace OpenSim.Region.Framework.Scenes
2081// m_log.DebugFormat( 2644// m_log.DebugFormat(
2082// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 2645// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2083// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 2646// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2084 2647
2648 if (m_rootPart.PhysActor != null)
2649 m_rootPart.PhysActor.Building = true;
2650
2085 linkPart.ClearUndoState(); 2651 linkPart.ClearUndoState();
2086 2652
2087 Quaternion worldRot = linkPart.GetWorldRotation(); 2653 Quaternion worldRot = linkPart.GetWorldRotation();
@@ -2141,6 +2707,10 @@ namespace OpenSim.Region.Framework.Scenes
2141 2707
2142 // When we delete a group, we currently have to force persist to the database if the object id has changed 2708 // When we delete a group, we currently have to force persist to the database if the object id has changed
2143 // (since delete works by deleting all rows which have a given object id) 2709 // (since delete works by deleting all rows which have a given object id)
2710
2711 if (m_rootPart.PhysActor != null)
2712 m_rootPart.PhysActor.Building = false;
2713
2144 objectGroup.HasGroupChangedDueToDelink = true; 2714 objectGroup.HasGroupChangedDueToDelink = true;
2145 2715
2146 return objectGroup; 2716 return objectGroup;
@@ -2152,6 +2722,7 @@ namespace OpenSim.Region.Framework.Scenes
2152 /// <param name="objectGroup"></param> 2722 /// <param name="objectGroup"></param>
2153 public virtual void DetachFromBackup() 2723 public virtual void DetachFromBackup()
2154 { 2724 {
2725 m_scene.SceneGraph.FireDetachFromBackup(this);
2155 if (m_isBackedUp && Scene != null) 2726 if (m_isBackedUp && Scene != null)
2156 m_scene.EventManager.OnBackup -= ProcessBackup; 2727 m_scene.EventManager.OnBackup -= ProcessBackup;
2157 2728
@@ -2170,7 +2741,8 @@ namespace OpenSim.Region.Framework.Scenes
2170 2741
2171 axPos *= parentRot; 2742 axPos *= parentRot;
2172 part.OffsetPosition = axPos; 2743 part.OffsetPosition = axPos;
2173 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2744 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2745 part.GroupPosition = newPos;
2174 part.OffsetPosition = Vector3.Zero; 2746 part.OffsetPosition = Vector3.Zero;
2175 part.RotationOffset = worldRot; 2747 part.RotationOffset = worldRot;
2176 2748
@@ -2181,7 +2753,7 @@ namespace OpenSim.Region.Framework.Scenes
2181 2753
2182 part.LinkNum = linkNum; 2754 part.LinkNum = linkNum;
2183 2755
2184 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2756 part.OffsetPosition = newPos - AbsolutePosition;
2185 2757
2186 Quaternion rootRotation = m_rootPart.RotationOffset; 2758 Quaternion rootRotation = m_rootPart.RotationOffset;
2187 2759
@@ -2191,7 +2763,7 @@ namespace OpenSim.Region.Framework.Scenes
2191 2763
2192 parentRot = m_rootPart.RotationOffset; 2764 parentRot = m_rootPart.RotationOffset;
2193 oldRot = part.RotationOffset; 2765 oldRot = part.RotationOffset;
2194 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2766 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2195 part.RotationOffset = newRot; 2767 part.RotationOffset = newRot;
2196 } 2768 }
2197 2769
@@ -2438,8 +3010,31 @@ namespace OpenSim.Region.Framework.Scenes
2438 } 3010 }
2439 } 3011 }
2440 3012
3013/*
3014 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2441 for (int i = 0; i < parts.Length; i++) 3015 for (int i = 0; i < parts.Length; i++)
2442 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3016 {
3017 if (parts[i] != RootPart)
3018 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
3019 }
3020*/
3021 if (parts.Length > 1)
3022 {
3023 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3024
3025 for (int i = 0; i < parts.Length; i++)
3026 {
3027
3028 if (parts[i].UUID != m_rootPart.UUID)
3029 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3030 }
3031
3032 if (m_rootPart.PhysActor != null)
3033 m_rootPart.PhysActor.Building = false;
3034 }
3035 else
3036 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
3037
2443 } 3038 }
2444 } 3039 }
2445 3040
@@ -2452,6 +3047,17 @@ namespace OpenSim.Region.Framework.Scenes
2452 } 3047 }
2453 } 3048 }
2454 3049
3050
3051
3052 /// <summary>
3053 /// Gets the number of parts
3054 /// </summary>
3055 /// <returns></returns>
3056 public int GetPartCount()
3057 {
3058 return Parts.Count();
3059 }
3060
2455 /// <summary> 3061 /// <summary>
2456 /// Update the texture entry for this part 3062 /// Update the texture entry for this part
2457 /// </summary> 3063 /// </summary>
@@ -2513,8 +3119,7 @@ namespace OpenSim.Region.Framework.Scenes
2513 { 3119 {
2514// m_log.DebugFormat( 3120// m_log.DebugFormat(
2515// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 3121// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2516 3122// RootPart.StoreUndoState(true);
2517 RootPart.StoreUndoState(true);
2518 3123
2519 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3124 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2520 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3125 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
@@ -2614,7 +3219,6 @@ namespace OpenSim.Region.Framework.Scenes
2614 prevScale.X *= x; 3219 prevScale.X *= x;
2615 prevScale.Y *= y; 3220 prevScale.Y *= y;
2616 prevScale.Z *= z; 3221 prevScale.Z *= z;
2617
2618// RootPart.IgnoreUndoUpdate = true; 3222// RootPart.IgnoreUndoUpdate = true;
2619 RootPart.Resize(prevScale); 3223 RootPart.Resize(prevScale);
2620// RootPart.IgnoreUndoUpdate = false; 3224// RootPart.IgnoreUndoUpdate = false;
@@ -2626,7 +3230,7 @@ namespace OpenSim.Region.Framework.Scenes
2626 3230
2627 if (obPart.UUID != m_rootPart.UUID) 3231 if (obPart.UUID != m_rootPart.UUID)
2628 { 3232 {
2629 obPart.IgnoreUndoUpdate = true; 3233// obPart.IgnoreUndoUpdate = true;
2630 3234
2631 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3235 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2632 currentpos.X *= x; 3236 currentpos.X *= x;
@@ -2641,11 +3245,13 @@ namespace OpenSim.Region.Framework.Scenes
2641 obPart.Resize(newSize); 3245 obPart.Resize(newSize);
2642 obPart.UpdateOffSet(currentpos); 3246 obPart.UpdateOffSet(currentpos);
2643 3247
2644 obPart.IgnoreUndoUpdate = false; 3248// obPart.IgnoreUndoUpdate = false;
2645 } 3249 }
2646 3250
2647// obPart.IgnoreUndoUpdate = false; 3251// obPart.IgnoreUndoUpdate = false;
2648// obPart.StoreUndoState(); 3252 HasGroupChanged = true;
3253 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3254 ScheduleGroupForTerseUpdate();
2649 } 3255 }
2650 3256
2651// m_log.DebugFormat( 3257// m_log.DebugFormat(
@@ -2664,7 +3270,7 @@ namespace OpenSim.Region.Framework.Scenes
2664 { 3270 {
2665// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos); 3271// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2666 3272
2667 RootPart.StoreUndoState(true); 3273// RootPart.StoreUndoState(true);
2668 3274
2669// SceneObjectPart[] parts = m_parts.GetArray(); 3275// SceneObjectPart[] parts = m_parts.GetArray();
2670// for (int i = 0; i < parts.Length; i++) 3276// for (int i = 0; i < parts.Length; i++)
@@ -2714,8 +3320,12 @@ namespace OpenSim.Region.Framework.Scenes
2714// m_log.DebugFormat( 3320// m_log.DebugFormat(
2715// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3321// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos);
2716 3322
2717 part.StoreUndoState(false); 3323// part.StoreUndoState(false);
2718 part.IgnoreUndoUpdate = true; 3324// part.IgnoreUndoUpdate = true;
3325
3326// unlock parts position change
3327 if (m_rootPart.PhysActor != null)
3328 m_rootPart.PhysActor.Building = true;
2719 3329
2720 if (part.UUID == m_rootPart.UUID) 3330 if (part.UUID == m_rootPart.UUID)
2721 { 3331 {
@@ -2726,8 +3336,11 @@ namespace OpenSim.Region.Framework.Scenes
2726 part.UpdateOffSet(pos); 3336 part.UpdateOffSet(pos);
2727 } 3337 }
2728 3338
3339 if (m_rootPart.PhysActor != null)
3340 m_rootPart.PhysActor.Building = false;
3341
2729 HasGroupChanged = true; 3342 HasGroupChanged = true;
2730 part.IgnoreUndoUpdate = false; 3343// part.IgnoreUndoUpdate = false;
2731 } 3344 }
2732 } 3345 }
2733 3346
@@ -2763,10 +3376,27 @@ namespace OpenSim.Region.Framework.Scenes
2763 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3376 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2764 } 3377 }
2765 3378
2766 AbsolutePosition = newPos; 3379 //We have to set undoing here because otherwise an undo state will be saved
3380// if (!m_rootPart.Undoing)
3381// {
3382// m_rootPart.Undoing = true;
3383 AbsolutePosition = newPos;
3384// m_rootPart.Undoing = false;
3385// }
3386// else
3387// {
3388// AbsolutePosition = newPos;
3389// }
2767 3390
2768 HasGroupChanged = true; 3391 HasGroupChanged = true;
2769 ScheduleGroupForTerseUpdate(); 3392 if (m_rootPart.Undoing)
3393 {
3394 ScheduleGroupForFullUpdate();
3395 }
3396 else
3397 {
3398 ScheduleGroupForTerseUpdate();
3399 }
2770 } 3400 }
2771 3401
2772 #endregion 3402 #endregion
@@ -2786,9 +3416,9 @@ namespace OpenSim.Region.Framework.Scenes
2786// for (int i = 0; i < parts.Length; i++) 3416// for (int i = 0; i < parts.Length; i++)
2787// parts[i].StoreUndoState(); 3417// parts[i].StoreUndoState();
2788 3418
2789 m_rootPart.StoreUndoState(true); 3419// m_rootPart.StoreUndoState(true);
2790 3420
2791 m_rootPart.UpdateRotation(rot); 3421// m_rootPart.UpdateRotation(rot);
2792 3422
2793 PhysicsActor actor = m_rootPart.PhysActor; 3423 PhysicsActor actor = m_rootPart.PhysActor;
2794 if (actor != null) 3424 if (actor != null)
@@ -2815,8 +3445,8 @@ namespace OpenSim.Region.Framework.Scenes
2815// for (int i = 0; i < parts.Length; i++) 3445// for (int i = 0; i < parts.Length; i++)
2816// parts[i].StoreUndoState(); 3446// parts[i].StoreUndoState();
2817 3447
2818 RootPart.StoreUndoState(true); 3448// RootPart.StoreUndoState(true);
2819 RootPart.IgnoreUndoUpdate = true; 3449// RootPart.IgnoreUndoUpdate = true;
2820 3450
2821 m_rootPart.UpdateRotation(rot); 3451 m_rootPart.UpdateRotation(rot);
2822 3452
@@ -2832,7 +3462,7 @@ namespace OpenSim.Region.Framework.Scenes
2832 HasGroupChanged = true; 3462 HasGroupChanged = true;
2833 ScheduleGroupForTerseUpdate(); 3463 ScheduleGroupForTerseUpdate();
2834 3464
2835 RootPart.IgnoreUndoUpdate = false; 3465// RootPart.IgnoreUndoUpdate = false;
2836 } 3466 }
2837 3467
2838 /// <summary> 3468 /// <summary>
@@ -2843,16 +3473,16 @@ namespace OpenSim.Region.Framework.Scenes
2843 public void UpdateSingleRotation(Quaternion rot, uint localID) 3473 public void UpdateSingleRotation(Quaternion rot, uint localID)
2844 { 3474 {
2845 SceneObjectPart part = GetChildPart(localID); 3475 SceneObjectPart part = GetChildPart(localID);
2846
2847 SceneObjectPart[] parts = m_parts.GetArray(); 3476 SceneObjectPart[] parts = m_parts.GetArray();
2848 for (int i = 0; i < parts.Length; i++)
2849 parts[i].StoreUndoState();
2850 3477
2851 if (part != null) 3478 if (part != null)
2852 { 3479 {
2853// m_log.DebugFormat( 3480// m_log.DebugFormat(
2854// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 3481// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot);
2855 3482
3483 if (m_rootPart.PhysActor != null)
3484 m_rootPart.PhysActor.Building = true;
3485
2856 if (part.UUID == m_rootPart.UUID) 3486 if (part.UUID == m_rootPart.UUID)
2857 { 3487 {
2858 UpdateRootRotation(rot); 3488 UpdateRootRotation(rot);
@@ -2861,6 +3491,9 @@ namespace OpenSim.Region.Framework.Scenes
2861 { 3491 {
2862 part.UpdateRotation(rot); 3492 part.UpdateRotation(rot);
2863 } 3493 }
3494
3495 if (m_rootPart.PhysActor != null)
3496 m_rootPart.PhysActor.Building = false;
2864 } 3497 }
2865 } 3498 }
2866 3499
@@ -2878,13 +3511,26 @@ namespace OpenSim.Region.Framework.Scenes
2878// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 3511// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}",
2879// part.Name, part.LocalId, rot); 3512// part.Name, part.LocalId, rot);
2880 3513
2881 part.StoreUndoState(); 3514// part.StoreUndoState();
2882 part.IgnoreUndoUpdate = true; 3515// part.IgnoreUndoUpdate = true;
3516
3517 if (m_rootPart.PhysActor != null)
3518 m_rootPart.PhysActor.Building = true;
2883 3519
2884 if (part.UUID == m_rootPart.UUID) 3520 if (part.UUID == m_rootPart.UUID)
2885 { 3521 {
2886 UpdateRootRotation(rot); 3522 UpdateRootRotation(rot);
2887 AbsolutePosition = pos; 3523/* if (!m_rootPart.Undoing)
3524 {
3525 m_rootPart.Undoing = true;
3526 AbsolutePosition = pos;
3527 m_rootPart.Undoing = false;
3528 }
3529 else
3530 {
3531 */
3532 AbsolutePosition = pos;
3533// }
2888 } 3534 }
2889 else 3535 else
2890 { 3536 {
@@ -2892,7 +3538,10 @@ namespace OpenSim.Region.Framework.Scenes
2892 part.OffsetPosition = pos; 3538 part.OffsetPosition = pos;
2893 } 3539 }
2894 3540
2895 part.IgnoreUndoUpdate = false; 3541 if (m_rootPart.PhysActor != null)
3542 m_rootPart.PhysActor.Building = false;
3543
3544// part.IgnoreUndoUpdate = false;
2896 } 3545 }
2897 } 3546 }
2898 3547
@@ -2908,9 +3557,10 @@ namespace OpenSim.Region.Framework.Scenes
2908 3557
2909 Quaternion axRot = rot; 3558 Quaternion axRot = rot;
2910 Quaternion oldParentRot = m_rootPart.RotationOffset; 3559 Quaternion oldParentRot = m_rootPart.RotationOffset;
2911 3560// m_rootPart.StoreUndoState();
2912 m_rootPart.StoreUndoState(); 3561
2913 m_rootPart.UpdateRotation(rot); 3562 //Don't use UpdateRotation because it schedules an update prematurely
3563 m_rootPart.RotationOffset = rot;
2914 if (m_rootPart.PhysActor != null) 3564 if (m_rootPart.PhysActor != null)
2915 { 3565 {
2916 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3566 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2923,17 +3573,19 @@ namespace OpenSim.Region.Framework.Scenes
2923 SceneObjectPart prim = parts[i]; 3573 SceneObjectPart prim = parts[i];
2924 if (prim.UUID != m_rootPart.UUID) 3574 if (prim.UUID != m_rootPart.UUID)
2925 { 3575 {
2926 prim.IgnoreUndoUpdate = true; 3576// prim.IgnoreUndoUpdate = true;
3577
3578 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3579 NewRot = Quaternion.Inverse(axRot) * NewRot;
3580 prim.RotationOffset = NewRot;
3581
2927 Vector3 axPos = prim.OffsetPosition; 3582 Vector3 axPos = prim.OffsetPosition;
3583
2928 axPos *= oldParentRot; 3584 axPos *= oldParentRot;
2929 axPos *= Quaternion.Inverse(axRot); 3585 axPos *= Quaternion.Inverse(axRot);
2930 prim.OffsetPosition = axPos; 3586 prim.OffsetPosition = axPos;
2931 Quaternion primsRot = prim.RotationOffset; 3587
2932 Quaternion newRot = oldParentRot * primsRot; 3588// prim.IgnoreUndoUpdate = false;
2933 newRot = Quaternion.Inverse(axRot) * newRot;
2934 prim.RotationOffset = newRot;
2935 prim.ScheduleTerseUpdate();
2936 prim.IgnoreUndoUpdate = false;
2937 } 3589 }
2938 } 3590 }
2939 3591
@@ -2946,8 +3598,8 @@ namespace OpenSim.Region.Framework.Scenes
2946//// childpart.StoreUndoState(); 3598//// childpart.StoreUndoState();
2947// } 3599// }
2948// } 3600// }
2949 3601 HasGroupChanged = true;
2950 m_rootPart.ScheduleTerseUpdate(); 3602 ScheduleGroupForFullUpdate();
2951 3603
2952// m_log.DebugFormat( 3604// m_log.DebugFormat(
2953// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3605// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3175,7 +3827,6 @@ namespace OpenSim.Region.Framework.Scenes
3175 public float GetMass() 3827 public float GetMass()
3176 { 3828 {
3177 float retmass = 0f; 3829 float retmass = 0f;
3178
3179 SceneObjectPart[] parts = m_parts.GetArray(); 3830 SceneObjectPart[] parts = m_parts.GetArray();
3180 for (int i = 0; i < parts.Length; i++) 3831 for (int i = 0; i < parts.Length; i++)
3181 retmass += parts[i].GetMass(); 3832 retmass += parts[i].GetMass();
@@ -3271,6 +3922,14 @@ namespace OpenSim.Region.Framework.Scenes
3271 SetFromItemID(uuid); 3922 SetFromItemID(uuid);
3272 } 3923 }
3273 3924
3925 public void ResetOwnerChangeFlag()
3926 {
3927 ForEachPart(delegate(SceneObjectPart part)
3928 {
3929 part.ResetOwnerChangeFlag();
3930 });
3931 }
3932
3274 #endregion 3933 #endregion
3275 } 3934 }
3276} 3935}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 439b718..6622495 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.
@@ -184,6 +185,15 @@ namespace OpenSim.Region.Framework.Scenes
184 185
185 public UUID FromFolderID; 186 public UUID FromFolderID;
186 187
188 // The following two are to hold the attachment data
189 // while an object is inworld
190 [XmlIgnore]
191 public byte AttachPoint = 0;
192
193 [XmlIgnore]
194 public Vector3 AttachOffset = Vector3.Zero;
195
196 [XmlIgnore]
187 public int STATUS_ROTATE_X; 197 public int STATUS_ROTATE_X;
188 198
189 public int STATUS_ROTATE_Y; 199 public int STATUS_ROTATE_Y;
@@ -210,8 +220,7 @@ namespace OpenSim.Region.Framework.Scenes
210 220
211 public Vector3 RotationAxis = Vector3.One; 221 public Vector3 RotationAxis = Vector3.One;
212 222
213 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 223 public bool VolumeDetectActive;
214 // Certainly this must be a persistant setting finally
215 224
216 public bool IsWaitingForFirstSpinUpdatePacket; 225 public bool IsWaitingForFirstSpinUpdatePacket;
217 226
@@ -251,10 +260,11 @@ namespace OpenSim.Region.Framework.Scenes
251 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 260 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
252 private Vector3 m_sitTargetPosition; 261 private Vector3 m_sitTargetPosition;
253 private string m_sitAnimation = "SIT"; 262 private string m_sitAnimation = "SIT";
263 private bool m_occupied; // KF if any av is sitting on this prim
254 private string m_text = String.Empty; 264 private string m_text = String.Empty;
255 private string m_touchName = String.Empty; 265 private string m_touchName = String.Empty;
256 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 266 private Stack<UndoState> m_undo = new Stack<UndoState>(5);
257 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5); 267 private Stack<UndoState> m_redo = new Stack<UndoState>(5);
258 268
259 private bool m_passTouches; 269 private bool m_passTouches;
260 270
@@ -283,6 +293,9 @@ namespace OpenSim.Region.Framework.Scenes
283 protected Vector3 m_lastAcceleration; 293 protected Vector3 m_lastAcceleration;
284 protected Vector3 m_lastAngularVelocity; 294 protected Vector3 m_lastAngularVelocity;
285 protected int m_lastTerseSent; 295 protected int m_lastTerseSent;
296 protected float m_buoyancy = 0.0f;
297 protected Vector3 m_force;
298 protected Vector3 m_torque;
286 299
287 /// <summary> 300 /// <summary>
288 /// Stores media texture data 301 /// Stores media texture data
@@ -299,6 +312,17 @@ namespace OpenSim.Region.Framework.Scenes
299 private UUID m_collisionSound; 312 private UUID m_collisionSound;
300 private float m_collisionSoundVolume; 313 private float m_collisionSoundVolume;
301 314
315
316 private SOPVehicle m_vehicle = null;
317
318 private KeyframeMotion m_keyframeMotion = null;
319
320 public KeyframeMotion KeyframeMotion
321 {
322 get; set;
323 }
324
325
302 #endregion Fields 326 #endregion Fields
303 327
304// ~SceneObjectPart() 328// ~SceneObjectPart()
@@ -341,7 +365,7 @@ namespace OpenSim.Region.Framework.Scenes
341 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 365 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
342 Quaternion rotationOffset, Vector3 offsetPosition) : this() 366 Quaternion rotationOffset, Vector3 offsetPosition) : this()
343 { 367 {
344 m_name = "Primitive"; 368 m_name = "Object";
345 369
346 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 370 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
347 LastOwnerID = CreatorID = OwnerID = ownerID; 371 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -381,7 +405,7 @@ namespace OpenSim.Region.Framework.Scenes
381 private uint _ownerMask = (uint)PermissionMask.All; 405 private uint _ownerMask = (uint)PermissionMask.All;
382 private uint _groupMask = (uint)PermissionMask.None; 406 private uint _groupMask = (uint)PermissionMask.None;
383 private uint _everyoneMask = (uint)PermissionMask.None; 407 private uint _everyoneMask = (uint)PermissionMask.None;
384 private uint _nextOwnerMask = (uint)PermissionMask.All; 408 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
385 private PrimFlags _flags = PrimFlags.None; 409 private PrimFlags _flags = PrimFlags.None;
386 private DateTime m_expires; 410 private DateTime m_expires;
387 private DateTime m_rezzed; 411 private DateTime m_rezzed;
@@ -475,12 +499,16 @@ namespace OpenSim.Region.Framework.Scenes
475 } 499 }
476 500
477 /// <value> 501 /// <value>
478 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 502 /// Get the inventory list
479 /// </value> 503 /// </value>
480 public TaskInventoryDictionary TaskInventory 504 public TaskInventoryDictionary TaskInventory
481 { 505 {
482 get { return m_inventory.Items; } 506 get {
483 set { m_inventory.Items = value; } 507 return m_inventory.Items;
508 }
509 set {
510 m_inventory.Items = value;
511 }
484 } 512 }
485 513
486 /// <summary> 514 /// <summary>
@@ -624,14 +652,12 @@ namespace OpenSim.Region.Framework.Scenes
624 set { m_LoopSoundSlavePrims = value; } 652 set { m_LoopSoundSlavePrims = value; }
625 } 653 }
626 654
627
628 public Byte[] TextureAnimation 655 public Byte[] TextureAnimation
629 { 656 {
630 get { return m_TextureAnimation; } 657 get { return m_TextureAnimation; }
631 set { m_TextureAnimation = value; } 658 set { m_TextureAnimation = value; }
632 } 659 }
633 660
634
635 public Byte[] ParticleSystem 661 public Byte[] ParticleSystem
636 { 662 {
637 get { return m_particleSystem; } 663 get { return m_particleSystem; }
@@ -668,9 +694,11 @@ namespace OpenSim.Region.Framework.Scenes
668 { 694 {
669 // If this is a linkset, we don't want the physics engine mucking up our group position here. 695 // If this is a linkset, we don't want the physics engine mucking up our group position here.
670 PhysicsActor actor = PhysActor; 696 PhysicsActor actor = PhysActor;
671 if (actor != null && ParentID == 0) 697 if (ParentID == 0)
672 { 698 {
673 m_groupPosition = actor.Position; 699 if (actor != null)
700 m_groupPosition = actor.Position;
701 return m_groupPosition;
674 } 702 }
675 703
676 if (ParentGroup.IsAttachment) 704 if (ParentGroup.IsAttachment)
@@ -680,12 +708,14 @@ namespace OpenSim.Region.Framework.Scenes
680 return sp.AbsolutePosition; 708 return sp.AbsolutePosition;
681 } 709 }
682 710
711 // use root prim's group position. Physics may have updated it
712 if (ParentGroup.RootPart != this)
713 m_groupPosition = ParentGroup.RootPart.GroupPosition;
683 return m_groupPosition; 714 return m_groupPosition;
684 } 715 }
685 set 716 set
686 { 717 {
687 m_groupPosition = value; 718 m_groupPosition = value;
688
689 PhysicsActor actor = PhysActor; 719 PhysicsActor actor = PhysActor;
690 if (actor != null) 720 if (actor != null)
691 { 721 {
@@ -711,16 +741,6 @@ namespace OpenSim.Region.Framework.Scenes
711 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 741 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
712 } 742 }
713 } 743 }
714
715 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
716 if (SitTargetAvatar != UUID.Zero)
717 {
718 ScenePresence avatar;
719 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
720 {
721 avatar.ParentPosition = GetWorldPosition();
722 }
723 }
724 } 744 }
725 } 745 }
726 746
@@ -729,7 +749,7 @@ namespace OpenSim.Region.Framework.Scenes
729 get { return m_offsetPosition; } 749 get { return m_offsetPosition; }
730 set 750 set
731 { 751 {
732// StoreUndoState(); 752 Vector3 oldpos = m_offsetPosition;
733 m_offsetPosition = value; 753 m_offsetPosition = value;
734 754
735 if (ParentGroup != null && !ParentGroup.IsDeleted) 755 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -744,7 +764,22 @@ namespace OpenSim.Region.Framework.Scenes
744 if (ParentGroup.Scene != null) 764 if (ParentGroup.Scene != null)
745 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 765 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
746 } 766 }
767
768 if (!m_parentGroup.m_dupeInProgress)
769 {
770 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
771 foreach (ScenePresence av in avs)
772 {
773 if (av.ParentID == m_localId)
774 {
775 Vector3 offset = (m_offsetPosition - oldpos);
776 av.AbsolutePosition += offset;
777 av.SendAvatarDataToAllAgents();
778 }
779 }
780 }
747 } 781 }
782 TriggerScriptChangedEvent(Changed.POSITION);
748 } 783 }
749 } 784 }
750 785
@@ -793,7 +828,7 @@ namespace OpenSim.Region.Framework.Scenes
793 828
794 set 829 set
795 { 830 {
796 StoreUndoState(); 831// StoreUndoState();
797 m_rotationOffset = value; 832 m_rotationOffset = value;
798 833
799 PhysicsActor actor = PhysActor; 834 PhysicsActor actor = PhysActor;
@@ -881,7 +916,7 @@ namespace OpenSim.Region.Framework.Scenes
881 get 916 get
882 { 917 {
883 PhysicsActor actor = PhysActor; 918 PhysicsActor actor = PhysActor;
884 if ((actor != null) && actor.IsPhysical) 919 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
885 { 920 {
886 m_angularVelocity = actor.RotationalVelocity; 921 m_angularVelocity = actor.RotationalVelocity;
887 } 922 }
@@ -893,7 +928,16 @@ namespace OpenSim.Region.Framework.Scenes
893 /// <summary></summary> 928 /// <summary></summary>
894 public Vector3 Acceleration 929 public Vector3 Acceleration
895 { 930 {
896 get { return m_acceleration; } 931 get
932 {
933 PhysicsActor actor = PhysActor;
934 if (actor != null)
935 {
936 m_acceleration = actor.Acceleration;
937 }
938 return m_acceleration;
939 }
940
897 set { m_acceleration = value; } 941 set { m_acceleration = value; }
898 } 942 }
899 943
@@ -963,7 +1007,7 @@ namespace OpenSim.Region.Framework.Scenes
963 { 1007 {
964 if (m_shape != null) 1008 if (m_shape != null)
965 { 1009 {
966 StoreUndoState(); 1010// StoreUndoState();
967 1011
968 m_shape.Scale = value; 1012 m_shape.Scale = value;
969 1013
@@ -1030,10 +1074,7 @@ namespace OpenSim.Region.Framework.Scenes
1030 { 1074 {
1031 get 1075 get
1032 { 1076 {
1033 if (ParentGroup.IsAttachment) 1077 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1034 return GroupPosition;
1035
1036 return m_offsetPosition + m_groupPosition;
1037 } 1078 }
1038 } 1079 }
1039 1080
@@ -1203,6 +1244,13 @@ namespace OpenSim.Region.Framework.Scenes
1203 _flags = value; 1244 _flags = value;
1204 } 1245 }
1205 } 1246 }
1247
1248 [XmlIgnore]
1249 public bool IsOccupied // KF If an av is sittingon this prim
1250 {
1251 get { return m_occupied; }
1252 set { m_occupied = value; }
1253 }
1206 1254
1207 /// <summary> 1255 /// <summary>
1208 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1256 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1262,6 +1310,74 @@ namespace OpenSim.Region.Framework.Scenes
1262 set { m_collisionSoundVolume = value; } 1310 set { m_collisionSoundVolume = value; }
1263 } 1311 }
1264 1312
1313 public float Buoyancy
1314 {
1315 get
1316 {
1317 if (ParentGroup.RootPart == this)
1318 return m_buoyancy;
1319
1320 return ParentGroup.RootPart.Buoyancy;
1321 }
1322 set
1323 {
1324 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1325 {
1326 ParentGroup.RootPart.Buoyancy = value;
1327 return;
1328 }
1329 m_buoyancy = value;
1330 if (PhysActor != null)
1331 PhysActor.Buoyancy = value;
1332 }
1333 }
1334
1335 public Vector3 Force
1336 {
1337 get
1338 {
1339 if (ParentGroup.RootPart == this)
1340 return m_force;
1341
1342 return ParentGroup.RootPart.Force;
1343 }
1344
1345 set
1346 {
1347 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1348 {
1349 ParentGroup.RootPart.Force = value;
1350 return;
1351 }
1352 m_force = value;
1353 if (PhysActor != null)
1354 PhysActor.Force = value;
1355 }
1356 }
1357
1358 public Vector3 Torque
1359 {
1360 get
1361 {
1362 if (ParentGroup.RootPart == this)
1363 return m_torque;
1364
1365 return ParentGroup.RootPart.Torque;
1366 }
1367
1368 set
1369 {
1370 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1371 {
1372 ParentGroup.RootPart.Torque = value;
1373 return;
1374 }
1375 m_torque = value;
1376 if (PhysActor != null)
1377 PhysActor.Torque = value;
1378 }
1379 }
1380
1265 #endregion Public Properties with only Get 1381 #endregion Public Properties with only Get
1266 1382
1267 private uint ApplyMask(uint val, bool set, uint mask) 1383 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1437,20 +1553,24 @@ namespace OpenSim.Region.Framework.Scenes
1437 /// </summary> 1553 /// </summary>
1438 /// <param name="impulsei">Vector force</param> 1554 /// <param name="impulsei">Vector force</param>
1439 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1555 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1440 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1556
1557 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1558 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1441 { 1559 {
1442 Vector3 impulse = impulsei; 1560 Vector3 torque = torquei;
1443 1561
1444 if (localGlobalTF) 1562 if (localGlobalTF)
1445 { 1563 {
1564/*
1446 Quaternion grot = GetWorldRotation(); 1565 Quaternion grot = GetWorldRotation();
1447 Quaternion AXgrot = grot; 1566 Quaternion AXgrot = grot;
1448 Vector3 AXimpulsei = impulsei; 1567 Vector3 AXimpulsei = impulsei;
1449 Vector3 newimpulse = AXimpulsei * AXgrot; 1568 Vector3 newimpulse = AXimpulsei * AXgrot;
1450 impulse = newimpulse; 1569 */
1570 torque *= GetWorldRotation();
1451 } 1571 }
1452 1572
1453 ParentGroup.setAngularImpulse(impulse); 1573 Torque = torque;
1454 } 1574 }
1455 1575
1456 /// <summary> 1576 /// <summary>
@@ -1458,7 +1578,8 @@ namespace OpenSim.Region.Framework.Scenes
1458 /// </summary> 1578 /// </summary>
1459 /// <param name="rootObjectFlags"></param> 1579 /// <param name="rootObjectFlags"></param>
1460 /// <param name="VolumeDetectActive"></param> 1580 /// <param name="VolumeDetectActive"></param>
1461 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 1581// public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive)
1582 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive, bool building)
1462 { 1583 {
1463 if (!ParentGroup.Scene.CollidablePrims) 1584 if (!ParentGroup.Scene.CollidablePrims)
1464 return; 1585 return;
@@ -1487,6 +1608,8 @@ namespace OpenSim.Region.Framework.Scenes
1487 // or flexible 1608 // or flexible
1488 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible)) 1609 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1489 { 1610 {
1611 Vector3 velocity = Velocity;
1612 Vector3 rotationalVelocity = AngularVelocity;
1490 try 1613 try
1491 { 1614 {
1492 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape( 1615 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
@@ -1494,7 +1617,8 @@ namespace OpenSim.Region.Framework.Scenes
1494 Shape, 1617 Shape,
1495 AbsolutePosition, 1618 AbsolutePosition,
1496 Scale, 1619 Scale,
1497 RotationOffset, 1620// RotationOffset,
1621 GetWorldRotation(), // physics wants world rotation
1498 RigidBody, 1622 RigidBody,
1499 m_localId); 1623 m_localId);
1500 } 1624 }
@@ -1509,8 +1633,29 @@ namespace OpenSim.Region.Framework.Scenes
1509 { 1633 {
1510 PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 1634 PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
1511 PhysActor.SetMaterial(Material); 1635 PhysActor.SetMaterial(Material);
1636
1637 // if root part apply vehicle
1638 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
1639 m_vehicle.SetVehicle(PhysActor);
1640
1512 DoPhysicsPropertyUpdate(RigidBody, true); 1641 DoPhysicsPropertyUpdate(RigidBody, true);
1513 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); 1642 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1643
1644 if (!building)
1645 PhysActor.Building = false;
1646
1647 Velocity = velocity;
1648 AngularVelocity = rotationalVelocity;
1649 PhysActor.Velocity = velocity;
1650 PhysActor.RotationalVelocity = rotationalVelocity;
1651
1652 // if not vehicle and root part apply force and torque
1653 if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
1654 && LocalId == ParentGroup.RootPart.LocalId)
1655 {
1656 PhysActor.Force = Force;
1657 PhysActor.Torque = Torque;
1658 }
1514 } 1659 }
1515 } 1660 }
1516 } 1661 }
@@ -1564,6 +1709,11 @@ namespace OpenSim.Region.Framework.Scenes
1564 dupe.Category = Category; 1709 dupe.Category = Category;
1565 dupe.m_rezzed = m_rezzed; 1710 dupe.m_rezzed = m_rezzed;
1566 1711
1712 dupe.m_undo = new Stack<UndoState>(5);
1713 dupe.m_redo = new Stack<UndoState>(5);
1714 dupe.IgnoreUndoUpdate = false;
1715 dupe.Undoing = false;
1716
1567 dupe.m_inventory = new SceneObjectPartInventory(dupe); 1717 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1568 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 1718 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1569 1719
@@ -1579,6 +1729,7 @@ namespace OpenSim.Region.Framework.Scenes
1579 1729
1580 // Move afterwards ResetIDs as it clears the localID 1730 // Move afterwards ResetIDs as it clears the localID
1581 dupe.LocalId = localID; 1731 dupe.LocalId = localID;
1732
1582 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1733 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1583 dupe.LastOwnerID = OwnerID; 1734 dupe.LastOwnerID = OwnerID;
1584 1735
@@ -1598,6 +1749,9 @@ namespace OpenSim.Region.Framework.Scenes
1598 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 1749 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1599 } 1750 }
1600 1751
1752 if (dupe.PhysActor != null)
1753 dupe.PhysActor.LocalID = localID;
1754
1601 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 1755 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1602 1756
1603// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 1757// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1740,6 +1894,11 @@ namespace OpenSim.Region.Framework.Scenes
1740 if (!isNew) 1894 if (!isNew)
1741 ParentGroup.Scene.RemovePhysicalPrim(1); 1895 ParentGroup.Scene.RemovePhysicalPrim(1);
1742 1896
1897 Velocity = new Vector3(0, 0, 0);
1898 Acceleration = new Vector3(0, 0, 0);
1899 if (ParentGroup.RootPart == this)
1900 AngularVelocity = new Vector3(0, 0, 0);
1901
1743 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 1902 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1744 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; 1903 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds;
1745 PhysActor.delink(); 1904 PhysActor.delink();
@@ -1762,7 +1921,8 @@ namespace OpenSim.Region.Framework.Scenes
1762 // velocity-vector. 1921 // velocity-vector.
1763 Velocity = new Vector3(0, 0, 0); 1922 Velocity = new Vector3(0, 0, 0);
1764 Acceleration = new Vector3(0, 0, 0); 1923 Acceleration = new Vector3(0, 0, 0);
1765 AngularVelocity = new Vector3(0, 0, 0); 1924 if (ParentGroup.RootPart == this)
1925 AngularVelocity = new Vector3(0, 0, 0);
1766 //RotationalVelocity = new Vector3(0, 0, 0); 1926 //RotationalVelocity = new Vector3(0, 0, 0);
1767 } 1927 }
1768 1928
@@ -1777,6 +1937,9 @@ namespace OpenSim.Region.Framework.Scenes
1777 { 1937 {
1778 if (UsePhysics) 1938 if (UsePhysics)
1779 { 1939 {
1940 if (ParentGroup.RootPart.KeyframeMotion != null)
1941 ParentGroup.RootPart.KeyframeMotion.Stop();
1942 ParentGroup.RootPart.KeyframeMotion = null;
1780 ParentGroup.Scene.AddPhysicalPrim(1); 1943 ParentGroup.Scene.AddPhysicalPrim(1);
1781 1944
1782 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 1945 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
@@ -1924,10 +2087,7 @@ namespace OpenSim.Region.Framework.Scenes
1924 2087
1925 public Vector3 GetForce() 2088 public Vector3 GetForce()
1926 { 2089 {
1927 if (PhysActor != null) 2090 return Force;
1928 return PhysActor.Force;
1929 else
1930 return Vector3.Zero;
1931 } 2091 }
1932 2092
1933 /// <summary> 2093 /// <summary>
@@ -2561,9 +2721,9 @@ namespace OpenSim.Region.Framework.Scenes
2561 Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0); 2721 Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0);
2562 2722
2563 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2723 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2564 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2724 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2565 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2725 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2566 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2726 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2567 { 2727 {
2568 ParentGroup.AbsolutePosition = newpos; 2728 ParentGroup.AbsolutePosition = newpos;
2569 return; 2729 return;
@@ -2584,17 +2744,18 @@ namespace OpenSim.Region.Framework.Scenes
2584 //Trys to fetch sound id from prim's inventory. 2744 //Trys to fetch sound id from prim's inventory.
2585 //Prim's inventory doesn't support non script items yet 2745 //Prim's inventory doesn't support non script items yet
2586 2746
2587 lock (TaskInventory) 2747 TaskInventory.LockItemsForRead(true);
2748
2749 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2588 { 2750 {
2589 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2751 if (item.Value.Name == sound)
2590 { 2752 {
2591 if (item.Value.Name == sound) 2753 soundID = item.Value.ItemID;
2592 { 2754 break;
2593 soundID = item.Value.ItemID;
2594 break;
2595 }
2596 } 2755 }
2597 } 2756 }
2757
2758 TaskInventory.LockItemsForRead(false);
2598 } 2759 }
2599 2760
2600 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2761 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2914,8 +3075,8 @@ namespace OpenSim.Region.Framework.Scenes
2914 { 3075 {
2915 const float ROTATION_TOLERANCE = 0.01f; 3076 const float ROTATION_TOLERANCE = 0.01f;
2916 const float VELOCITY_TOLERANCE = 0.001f; 3077 const float VELOCITY_TOLERANCE = 0.001f;
2917 const float POSITION_TOLERANCE = 0.05f; 3078 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2918 const int TIME_MS_TOLERANCE = 3000; 3079 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2919 3080
2920 switch (UpdateFlag) 3081 switch (UpdateFlag)
2921 { 3082 {
@@ -2977,17 +3138,16 @@ namespace OpenSim.Region.Framework.Scenes
2977 if (!UUID.TryParse(sound, out soundID)) 3138 if (!UUID.TryParse(sound, out soundID))
2978 { 3139 {
2979 // search sound file from inventory 3140 // search sound file from inventory
2980 lock (TaskInventory) 3141 TaskInventory.LockItemsForRead(true);
3142 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2981 { 3143 {
2982 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3144 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2983 { 3145 {
2984 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3146 soundID = item.Value.ItemID;
2985 { 3147 break;
2986 soundID = item.Value.ItemID;
2987 break;
2988 }
2989 } 3148 }
2990 } 3149 }
3150 TaskInventory.LockItemsForRead(false);
2991 } 3151 }
2992 3152
2993 if (soundID == UUID.Zero) 3153 if (soundID == UUID.Zero)
@@ -3072,10 +3232,13 @@ namespace OpenSim.Region.Framework.Scenes
3072 3232
3073 public void SetBuoyancy(float fvalue) 3233 public void SetBuoyancy(float fvalue)
3074 { 3234 {
3235 Buoyancy = fvalue;
3236/*
3075 if (PhysActor != null) 3237 if (PhysActor != null)
3076 { 3238 {
3077 PhysActor.Buoyancy = fvalue; 3239 PhysActor.Buoyancy = fvalue;
3078 } 3240 }
3241 */
3079 } 3242 }
3080 3243
3081 public void SetDieAtEdge(bool p) 3244 public void SetDieAtEdge(bool p)
@@ -3103,23 +3266,83 @@ namespace OpenSim.Region.Framework.Scenes
3103 3266
3104 public void SetForce(Vector3 force) 3267 public void SetForce(Vector3 force)
3105 { 3268 {
3269 Force = force;
3270/*
3106 if (PhysActor != null) 3271 if (PhysActor != null)
3107 { 3272 {
3108 PhysActor.Force = force; 3273 PhysActor.Force = force;
3109 } 3274 }
3275 */
3276 }
3277
3278 public SOPVehicle sopVehicle
3279 {
3280 get
3281 {
3282 return m_vehicle;
3283 }
3284 set
3285 {
3286 m_vehicle = value;
3287 }
3288 }
3289
3290
3291 public int VehicleType
3292 {
3293 get
3294 {
3295 if (m_vehicle == null)
3296 return (int)Vehicle.TYPE_NONE;
3297 else
3298 return (int)m_vehicle.Type;
3299 }
3300 set
3301 {
3302 SetVehicleType(value);
3303 }
3110 } 3304 }
3111 3305
3112 public void SetVehicleType(int type) 3306 public void SetVehicleType(int type)
3113 { 3307 {
3114 if (PhysActor != null) 3308 m_vehicle = null;
3309
3310 if (type == (int)Vehicle.TYPE_NONE)
3311 {
3312 if (_parentID ==0 && PhysActor != null)
3313 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3314 return;
3315 }
3316 m_vehicle = new SOPVehicle();
3317 m_vehicle.ProcessTypeChange((Vehicle)type);
3318 {
3319 if (_parentID ==0 && PhysActor != null)
3320 PhysActor.VehicleType = type;
3321 return;
3322 }
3323 }
3324
3325 public void SetVehicleFlags(int param, bool remove)
3326 {
3327 if (m_vehicle == null)
3328 return;
3329
3330 m_vehicle.ProcessVehicleFlags(param, remove);
3331
3332 if (_parentID ==0 && PhysActor != null)
3115 { 3333 {
3116 PhysActor.VehicleType = type; 3334 PhysActor.VehicleFlags(param, remove);
3117 } 3335 }
3118 } 3336 }
3119 3337
3120 public void SetVehicleFloatParam(int param, float value) 3338 public void SetVehicleFloatParam(int param, float value)
3121 { 3339 {
3122 if (PhysActor != null) 3340 if (m_vehicle == null)
3341 return;
3342
3343 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
3344
3345 if (_parentID == 0 && PhysActor != null)
3123 { 3346 {
3124 PhysActor.VehicleFloatParam(param, value); 3347 PhysActor.VehicleFloatParam(param, value);
3125 } 3348 }
@@ -3127,7 +3350,12 @@ namespace OpenSim.Region.Framework.Scenes
3127 3350
3128 public void SetVehicleVectorParam(int param, Vector3 value) 3351 public void SetVehicleVectorParam(int param, Vector3 value)
3129 { 3352 {
3130 if (PhysActor != null) 3353 if (m_vehicle == null)
3354 return;
3355
3356 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
3357
3358 if (_parentID == 0 && PhysActor != null)
3131 { 3359 {
3132 PhysActor.VehicleVectorParam(param, value); 3360 PhysActor.VehicleVectorParam(param, value);
3133 } 3361 }
@@ -3135,7 +3363,12 @@ namespace OpenSim.Region.Framework.Scenes
3135 3363
3136 public void SetVehicleRotationParam(int param, Quaternion rotation) 3364 public void SetVehicleRotationParam(int param, Quaternion rotation)
3137 { 3365 {
3138 if (PhysActor != null) 3366 if (m_vehicle == null)
3367 return;
3368
3369 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
3370
3371 if (_parentID == 0 && PhysActor != null)
3139 { 3372 {
3140 PhysActor.VehicleRotationParam(param, rotation); 3373 PhysActor.VehicleRotationParam(param, rotation);
3141 } 3374 }
@@ -3322,13 +3555,6 @@ namespace OpenSim.Region.Framework.Scenes
3322 hasProfileCut = hasDimple; // is it the same thing? 3555 hasProfileCut = hasDimple; // is it the same thing?
3323 } 3556 }
3324 3557
3325 public void SetVehicleFlags(int param, bool remove)
3326 {
3327 if (PhysActor != null)
3328 {
3329 PhysActor.VehicleFlags(param, remove);
3330 }
3331 }
3332 3558
3333 public void SetGroup(UUID groupID, IClientAPI client) 3559 public void SetGroup(UUID groupID, IClientAPI client)
3334 { 3560 {
@@ -3438,61 +3664,38 @@ namespace OpenSim.Region.Framework.Scenes
3438 3664
3439 public void StoreUndoState(bool forGroup) 3665 public void StoreUndoState(bool forGroup)
3440 { 3666 {
3441 if (!Undoing) 3667 if (!Undoing && !IgnoreUndoUpdate) // just to read better - undo is in progress, or suspended
3442 { 3668 {
3443 if (!IgnoreUndoUpdate) 3669 if (ParentGroup != null)
3444 { 3670 {
3445 if (ParentGroup != null) 3671 lock (m_undo)
3446 { 3672 {
3447 lock (m_undo) 3673 if (m_undo.Count > 0)
3448 { 3674 {
3449 if (m_undo.Count > 0) 3675 // see if we had a change
3450 { 3676
3451 UndoState last = m_undo.Peek(); 3677 UndoState last = m_undo.Peek();
3452 if (last != null) 3678 if (last != null)
3679 {
3680 if (last.Compare(this, forGroup))
3453 { 3681 {
3454 // TODO: May need to fix for group comparison 3682 return;
3455 if (last.Compare(this))
3456 {
3457 // m_log.DebugFormat(
3458 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3459 // Name, LocalId, m_undo.Count);
3460
3461 return;
3462 }
3463 } 3683 }
3464 } 3684 }
3465 3685 }
3466 // m_log.DebugFormat( 3686
3467 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", 3687 if (ParentGroup.GetSceneMaxUndo() > 0)
3468 // Name, LocalId, forGroup, m_undo.Count); 3688 {
3469 3689 UndoState nUndo = new UndoState(this, forGroup);
3470 if (ParentGroup.GetSceneMaxUndo() > 0) 3690
3471 { 3691 m_undo.Push(nUndo);
3472 UndoState nUndo = new UndoState(this, forGroup); 3692
3473 3693 if (m_redo.Count > 0)
3474 m_undo.Push(nUndo); 3694 m_redo.Clear();
3475
3476 if (m_redo.Count > 0)
3477 m_redo.Clear();
3478
3479 // m_log.DebugFormat(
3480 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3481 // Name, LocalId, forGroup, m_undo.Count);
3482 }
3483 } 3695 }
3484 } 3696 }
3485 } 3697 }
3486// else
3487// {
3488// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3489// }
3490 } 3698 }
3491// else
3492// {
3493// m_log.DebugFormat(
3494// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3495// }
3496 } 3699 }
3497 3700
3498 /// <summary> 3701 /// <summary>
@@ -3528,7 +3731,7 @@ namespace OpenSim.Region.Framework.Scenes
3528 nUndo = new UndoState(this, goback.ForGroup); 3731 nUndo = new UndoState(this, goback.ForGroup);
3529 } 3732 }
3530 3733
3531 goback.PlaybackState(this); 3734 goback.PlayState(this);
3532 3735
3533 if (nUndo != null) 3736 if (nUndo != null)
3534 m_redo.Push(nUndo); 3737 m_redo.Push(nUndo);
@@ -3562,7 +3765,7 @@ namespace OpenSim.Region.Framework.Scenes
3562 m_undo.Push(nUndo); 3765 m_undo.Push(nUndo);
3563 } 3766 }
3564 3767
3565 gofwd.PlayfwdState(this); 3768 gofwd.PlayState(this);
3566 } 3769 }
3567 3770
3568// m_log.DebugFormat( 3771// m_log.DebugFormat(
@@ -4216,13 +4419,17 @@ namespace OpenSim.Region.Framework.Scenes
4216 /// <param name="SetTemporary"></param> 4419 /// <param name="SetTemporary"></param>
4217 /// <param name="SetPhantom"></param> 4420 /// <param name="SetPhantom"></param>
4218 /// <param name="SetVD"></param> 4421 /// <param name="SetVD"></param>
4219 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4422// public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD)
4423 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4220 { 4424 {
4221 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4425 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4222 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4426 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
4223 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0); 4427 bool wasPhantom = ((Flags & PrimFlags.Phantom) != 0);
4224 bool wasVD = VolumeDetectActive; 4428 bool wasVD = VolumeDetectActive;
4225 4429
4430// m_log.DebugFormat("[SOP]: Old states: phys: {0} temp: {1} phan: {2} vd: {3}", wasUsingPhysics, wasTemporary, wasPhantom, wasVD);
4431// m_log.DebugFormat("[SOP]: New states: phys: {0} temp: {1} phan: {2} vd: {3}", UsePhysics, SetTemporary, SetPhantom, SetVD);
4432
4226 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4433 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4227 return; 4434 return;
4228 4435
@@ -4231,6 +4438,9 @@ namespace OpenSim.Region.Framework.Scenes
4231 // that... 4438 // that...
4232 // ... if VD is changed, all others are not. 4439 // ... if VD is changed, all others are not.
4233 // ... if one of the others is changed, VD is not. 4440 // ... if one of the others is changed, VD is not.
4441 // do this first
4442 if (building && PhysActor != null && PhysActor.Building != building)
4443 PhysActor.Building = building;
4234 if (SetVD) // VD is active, special logic applies 4444 if (SetVD) // VD is active, special logic applies
4235 { 4445 {
4236 // State machine logic for VolumeDetect 4446 // State machine logic for VolumeDetect
@@ -4252,6 +4462,11 @@ namespace OpenSim.Region.Framework.Scenes
4252 SetPhantom = false; 4462 SetPhantom = false;
4253 } 4463 }
4254 } 4464 }
4465 else if (wasVD)
4466 {
4467 // Correspondingly, if VD is turned off, also turn off phantom
4468 SetPhantom = false;
4469 }
4255 4470
4256 if (UsePhysics && IsJoint()) 4471 if (UsePhysics && IsJoint())
4257 { 4472 {
@@ -4307,11 +4522,17 @@ namespace OpenSim.Region.Framework.Scenes
4307 Shape, 4522 Shape,
4308 AbsolutePosition, 4523 AbsolutePosition,
4309 Scale, 4524 Scale,
4310 RotationOffset, 4525// RotationOffset,
4526 GetWorldRotation(), //physics wants world rotation like all other functions send
4311 UsePhysics, 4527 UsePhysics,
4312 m_localId); 4528 m_localId);
4313 4529
4314 PhysActor.SetMaterial(Material); 4530 PhysActor.SetMaterial(Material);
4531
4532 // if root part apply vehicle
4533 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
4534 m_vehicle.SetVehicle(PhysActor);
4535
4315 DoPhysicsPropertyUpdate(UsePhysics, true); 4536 DoPhysicsPropertyUpdate(UsePhysics, true);
4316 4537
4317 if (!ParentGroup.IsDeleted) 4538 if (!ParentGroup.IsDeleted)
@@ -4387,6 +4608,9 @@ namespace OpenSim.Region.Framework.Scenes
4387 } 4608 }
4388 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4609 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4389 4610
4611 // and last in case we have a new actor and not building
4612 if (PhysActor != null && PhysActor.Building != building)
4613 PhysActor.Building = building;
4390 if (ParentGroup != null) 4614 if (ParentGroup != null)
4391 { 4615 {
4392 ParentGroup.HasGroupChanged = true; 4616 ParentGroup.HasGroupChanged = true;
@@ -4750,5 +4974,17 @@ namespace OpenSim.Region.Framework.Scenes
4750 Color color = Color; 4974 Color color = Color;
4751 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4975 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4752 } 4976 }
4977
4978 public void ResetOwnerChangeFlag()
4979 {
4980 List<UUID> inv = Inventory.GetInventoryList();
4981
4982 foreach (UUID itemID in inv)
4983 {
4984 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4985 item.OwnerChanged = false;
4986 Inventory.UpdateInventoryItem(item, false, false);
4987 }
4988 }
4753 } 4989 }
4754} 4990}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index f2d1915..ca85d10 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 }
217 } 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 }
260 }
261
262 Items.LockItemsForRead(false);
218 } 263 }
219 264
220 /// <summary> 265 /// <summary>
@@ -222,9 +267,14 @@ namespace OpenSim.Region.Framework.Scenes
222 /// </summary> 267 /// </summary>
223 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
224 { 269 {
225 List<TaskInventoryItem> scripts = GetInventoryScripts(); 270 Items.LockItemsForRead(true);
226 foreach (TaskInventoryItem item in scripts) 271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
227 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 272 Items.LockItemsForRead(false);
273 foreach (TaskInventoryItem item in items)
274 {
275 if ((int)InventoryType.LSL == item.InvType)
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
277 }
228 } 278 }
229 279
230 public ArrayList GetScriptErrors(UUID itemID) 280 public ArrayList GetScriptErrors(UUID itemID)
@@ -255,9 +305,18 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </param> 305 /// </param>
256 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 306 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
257 { 307 {
258 List<TaskInventoryItem> scripts = GetInventoryScripts(); 308 Items.LockItemsForRead(true);
259 foreach (TaskInventoryItem item in scripts) 309 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 310 Items.LockItemsForRead(false);
311
312 foreach (TaskInventoryItem item in items)
313 {
314 if ((int)InventoryType.LSL == item.InvType)
315 {
316 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
317 m_part.RemoveScriptEvents(item.ItemID);
318 }
319 }
261 } 320 }
262 321
263 /// <summary> 322 /// <summary>
@@ -271,7 +330,10 @@ namespace OpenSim.Region.Framework.Scenes
271// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 330// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
272 331
273 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 332 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
333 {
334 StoreScriptError(item.ItemID, "no permission");
274 return; 335 return;
336 }
275 337
276 m_part.AddFlag(PrimFlags.Scripted); 338 m_part.AddFlag(PrimFlags.Scripted);
277 339
@@ -280,14 +342,13 @@ namespace OpenSim.Region.Framework.Scenes
280 if (stateSource == 2 && // Prim crossing 342 if (stateSource == 2 && // Prim crossing
281 m_part.ParentGroup.Scene.m_trustBinaries) 343 m_part.ParentGroup.Scene.m_trustBinaries)
282 { 344 {
283 lock (m_items) 345 m_items.LockItemsForWrite(true);
284 { 346 m_items[item.ItemID].PermsMask = 0;
285 m_items[item.ItemID].PermsMask = 0; 347 m_items[item.ItemID].PermsGranter = UUID.Zero;
286 m_items[item.ItemID].PermsGranter = UUID.Zero; 348 m_items.LockItemsForWrite(false);
287 }
288
289 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 349 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
290 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 350 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
351 StoreScriptErrors(item.ItemID, null);
291 m_part.ParentGroup.AddActiveScriptCount(1); 352 m_part.ParentGroup.AddActiveScriptCount(1);
292 m_part.ScheduleFullUpdate(); 353 m_part.ScheduleFullUpdate();
293 return; 354 return;
@@ -296,6 +357,8 @@ namespace OpenSim.Region.Framework.Scenes
296 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 357 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
297 if (null == asset) 358 if (null == asset)
298 { 359 {
360 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
361 StoreScriptError(item.ItemID, msg);
299 m_log.ErrorFormat( 362 m_log.ErrorFormat(
300 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 363 "[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, 364 item.Name, item.ItemID, m_part.AbsolutePosition,
@@ -306,16 +369,21 @@ namespace OpenSim.Region.Framework.Scenes
306 if (m_part.ParentGroup.m_savedScriptState != null) 369 if (m_part.ParentGroup.m_savedScriptState != null)
307 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 370 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
308 371
309 lock (m_items) 372 m_items.LockItemsForWrite(true);
310 {
311 m_items[item.ItemID].OldItemID = item.OldItemID;
312 m_items[item.ItemID].PermsMask = 0;
313 m_items[item.ItemID].PermsGranter = UUID.Zero;
314 }
315 373
374 m_items[item.ItemID].OldItemID = item.OldItemID;
375 m_items[item.ItemID].PermsMask = 0;
376 m_items[item.ItemID].PermsGranter = UUID.Zero;
377
378 m_items.LockItemsForWrite(false);
379
316 string script = Utils.BytesToString(asset.Data); 380 string script = Utils.BytesToString(asset.Data);
317 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 381 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
318 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 382 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
383 StoreScriptErrors(item.ItemID, null);
384 if (!item.ScriptRunning)
385 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
386 m_part.LocalId, item.ItemID);
319 m_part.ParentGroup.AddActiveScriptCount(1); 387 m_part.ParentGroup.AddActiveScriptCount(1);
320 m_part.ScheduleFullUpdate(); 388 m_part.ScheduleFullUpdate();
321 } 389 }
@@ -386,20 +454,146 @@ namespace OpenSim.Region.Framework.Scenes
386 454
387 /// <summary> 455 /// <summary>
388 /// Start a script which is in this prim's inventory. 456 /// Start a script which is in this prim's inventory.
457 /// Some processing may occur in the background, but this routine returns asap.
389 /// </summary> 458 /// </summary>
390 /// <param name="itemId"> 459 /// <param name="itemId">
391 /// A <see cref="UUID"/> 460 /// A <see cref="UUID"/>
392 /// </param> 461 /// </param>
393 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 462 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
394 { 463 {
395 TaskInventoryItem item = GetInventoryItem(itemId); 464 lock (m_scriptErrors)
396 if (item != null) 465 {
397 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 466 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
467 m_scriptErrors.Remove(itemId);
468 }
469 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
470 }
471
472 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
473 {
474 m_items.LockItemsForRead(true);
475 if (m_items.ContainsKey(itemId))
476 {
477 if (m_items.ContainsKey(itemId))
478 {
479 m_items.LockItemsForRead(false);
480 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
481 }
482 else
483 {
484 m_items.LockItemsForRead(false);
485 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
486 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
487 StoreScriptError(itemId, msg);
488 m_log.ErrorFormat(
489 "[PRIM INVENTORY]: " +
490 "Couldn't start script with ID {0} since it {1}", itemId, msg);
491 }
492 }
398 else 493 else
494 {
495 m_items.LockItemsForRead(false);
496 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
497 StoreScriptError(itemId, msg);
399 m_log.ErrorFormat( 498 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}", 499 "[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, 500 itemId, m_part.Name, m_part.UUID,
402 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 501 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
502 }
503
504 }
505
506 /// <summary>
507 /// Start a script which is in this prim's inventory and return any compilation error messages.
508 /// </summary>
509 /// <param name="itemId">
510 /// A <see cref="UUID"/>
511 /// </param>
512 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
513 {
514 ArrayList errors;
515
516 // Indicate to CreateScriptInstanceInternal() we want it to
517 // post any compilation/loading error messages
518 lock (m_scriptErrors)
519 {
520 m_scriptErrors[itemId] = null;
521 }
522
523 // Perform compilation/loading
524 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
525
526 // Wait for and retrieve any errors
527 lock (m_scriptErrors)
528 {
529 while ((errors = m_scriptErrors[itemId]) == null)
530 {
531 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
532 {
533 m_log.ErrorFormat(
534 "[PRIM INVENTORY]: " +
535 "timedout waiting for script {0} errors", itemId);
536 errors = m_scriptErrors[itemId];
537 if (errors == null)
538 {
539 errors = new ArrayList(1);
540 errors.Add("timedout waiting for errors");
541 }
542 break;
543 }
544 }
545 m_scriptErrors.Remove(itemId);
546 }
547 return errors;
548 }
549
550 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
551 private void StoreScriptErrors(UUID itemId, ArrayList errors)
552 {
553 lock (m_scriptErrors)
554 {
555 // If compilation/loading initiated via CreateScriptInstance(),
556 // it does not want the errors, so just get out
557 if (!m_scriptErrors.ContainsKey(itemId))
558 {
559 return;
560 }
561
562 // Initiated via CreateScriptInstanceEr(), if we know what the
563 // errors are, save them and wake CreateScriptInstanceEr().
564 if (errors != null)
565 {
566 m_scriptErrors[itemId] = errors;
567 System.Threading.Monitor.PulseAll(m_scriptErrors);
568 return;
569 }
570 }
571
572 // Initiated via CreateScriptInstanceEr() but we don't know what
573 // the errors are yet, so retrieve them from the script engine.
574 // This may involve some waiting internal to GetScriptErrors().
575 errors = GetScriptErrors(itemId);
576
577 // Get a default non-null value to indicate success.
578 if (errors == null)
579 {
580 errors = new ArrayList();
581 }
582
583 // Post to CreateScriptInstanceEr() and wake it up
584 lock (m_scriptErrors)
585 {
586 m_scriptErrors[itemId] = errors;
587 System.Threading.Monitor.PulseAll(m_scriptErrors);
588 }
589 }
590
591 // Like StoreScriptErrors(), but just posts a single string message
592 private void StoreScriptError(UUID itemId, string message)
593 {
594 ArrayList errors = new ArrayList(1);
595 errors.Add(message);
596 StoreScriptErrors(itemId, errors);
403 } 597 }
404 598
405 /// <summary> 599 /// <summary>
@@ -412,15 +606,7 @@ namespace OpenSim.Region.Framework.Scenes
412 /// </param> 606 /// </param>
413 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 607 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
414 { 608 {
415 bool scriptPresent = false; 609 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 { 610 {
425 if (!sceneObjectBeingDeleted) 611 if (!sceneObjectBeingDeleted)
426 m_part.RemoveScriptEvents(itemId); 612 m_part.RemoveScriptEvents(itemId);
@@ -445,14 +631,16 @@ namespace OpenSim.Region.Framework.Scenes
445 /// <returns></returns> 631 /// <returns></returns>
446 private bool InventoryContainsName(string name) 632 private bool InventoryContainsName(string name)
447 { 633 {
448 lock (m_items) 634 m_items.LockItemsForRead(true);
635 foreach (TaskInventoryItem item in m_items.Values)
449 { 636 {
450 foreach (TaskInventoryItem item in m_items.Values) 637 if (item.Name == name)
451 { 638 {
452 if (item.Name == name) 639 m_items.LockItemsForRead(false);
453 return true; 640 return true;
454 } 641 }
455 } 642 }
643 m_items.LockItemsForRead(false);
456 return false; 644 return false;
457 } 645 }
458 646
@@ -494,8 +682,9 @@ namespace OpenSim.Region.Framework.Scenes
494 /// <param name="item"></param> 682 /// <param name="item"></param>
495 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 683 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
496 { 684 {
497 List<TaskInventoryItem> il = GetInventoryItems(); 685 m_items.LockItemsForRead(true);
498 686 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
687 m_items.LockItemsForRead(false);
499 foreach (TaskInventoryItem i in il) 688 foreach (TaskInventoryItem i in il)
500 { 689 {
501 if (i.Name == item.Name) 690 if (i.Name == item.Name)
@@ -533,14 +722,14 @@ namespace OpenSim.Region.Framework.Scenes
533 item.Name = name; 722 item.Name = name;
534 item.GroupID = m_part.GroupID; 723 item.GroupID = m_part.GroupID;
535 724
536 lock (m_items) 725 m_items.LockItemsForWrite(true);
537 m_items.Add(item.ItemID, item); 726 m_items.Add(item.ItemID, item);
538 727 m_items.LockItemsForWrite(false);
539 if (allowedDrop) 728 if (allowedDrop)
540 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 729 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
541 else 730 else
542 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 731 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
543 732
544 m_inventorySerial++; 733 m_inventorySerial++;
545 //m_inventorySerial += 2; 734 //m_inventorySerial += 2;
546 HasInventoryChanged = true; 735 HasInventoryChanged = true;
@@ -556,15 +745,15 @@ namespace OpenSim.Region.Framework.Scenes
556 /// <param name="items"></param> 745 /// <param name="items"></param>
557 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 746 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
558 { 747 {
559 lock (m_items) 748 m_items.LockItemsForWrite(true);
749 foreach (TaskInventoryItem item in items)
560 { 750 {
561 foreach (TaskInventoryItem item in items) 751 m_items.Add(item.ItemID, item);
562 { 752// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
563 m_items.Add(item.ItemID, item);
564// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
565 }
566 m_inventorySerial++;
567 } 753 }
754 m_items.LockItemsForWrite(false);
755
756 m_inventorySerial++;
568 } 757 }
569 758
570 /// <summary> 759 /// <summary>
@@ -575,10 +764,9 @@ namespace OpenSim.Region.Framework.Scenes
575 public TaskInventoryItem GetInventoryItem(UUID itemId) 764 public TaskInventoryItem GetInventoryItem(UUID itemId)
576 { 765 {
577 TaskInventoryItem item; 766 TaskInventoryItem item;
578 767 m_items.LockItemsForRead(true);
579 lock (m_items) 768 m_items.TryGetValue(itemId, out item);
580 m_items.TryGetValue(itemId, out item); 769 m_items.LockItemsForRead(false);
581
582 return item; 770 return item;
583 } 771 }
584 772
@@ -594,15 +782,16 @@ namespace OpenSim.Region.Framework.Scenes
594 { 782 {
595 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 783 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
596 784
597 lock (m_items) 785 m_items.LockItemsForRead(true);
786
787 foreach (TaskInventoryItem item in m_items.Values)
598 { 788 {
599 foreach (TaskInventoryItem item in m_items.Values) 789 if (item.Name == name)
600 { 790 items.Add(item);
601 if (item.Name == name)
602 items.Add(item);
603 }
604 } 791 }
605 792
793 m_items.LockItemsForRead(false);
794
606 return items; 795 return items;
607 } 796 }
608 797
@@ -621,6 +810,9 @@ namespace OpenSim.Region.Framework.Scenes
621 string xmlData = Utils.BytesToString(rezAsset.Data); 810 string xmlData = Utils.BytesToString(rezAsset.Data);
622 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 811 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
623 812
813 group.RootPart.AttachPoint = group.RootPart.Shape.State;
814 group.RootPart.AttachOffset = group.AbsolutePosition;
815
624 group.ResetIDs(); 816 group.ResetIDs();
625 817
626 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 818 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -695,8 +887,9 @@ namespace OpenSim.Region.Framework.Scenes
695 887
696 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 888 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
697 { 889 {
698 TaskInventoryItem it = GetInventoryItem(item.ItemID); 890 m_items.LockItemsForWrite(true);
699 if (it != null) 891
892 if (m_items.ContainsKey(item.ItemID))
700 { 893 {
701// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 894// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
702 895
@@ -709,14 +902,10 @@ namespace OpenSim.Region.Framework.Scenes
709 item.GroupID = m_part.GroupID; 902 item.GroupID = m_part.GroupID;
710 903
711 if (item.AssetID == UUID.Zero) 904 if (item.AssetID == UUID.Zero)
712 item.AssetID = it.AssetID; 905 item.AssetID = m_items[item.ItemID].AssetID;
713 906
714 lock (m_items) 907 m_items[item.ItemID] = item;
715 { 908 m_inventorySerial++;
716 m_items[item.ItemID] = item;
717 m_inventorySerial++;
718 }
719
720 if (fireScriptEvents) 909 if (fireScriptEvents)
721 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 910 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
722 911
@@ -725,7 +914,7 @@ namespace OpenSim.Region.Framework.Scenes
725 HasInventoryChanged = true; 914 HasInventoryChanged = true;
726 m_part.ParentGroup.HasGroupChanged = true; 915 m_part.ParentGroup.HasGroupChanged = true;
727 } 916 }
728 917 m_items.LockItemsForWrite(false);
729 return true; 918 return true;
730 } 919 }
731 else 920 else
@@ -736,8 +925,9 @@ namespace OpenSim.Region.Framework.Scenes
736 item.ItemID, m_part.Name, m_part.UUID, 925 item.ItemID, m_part.Name, m_part.UUID,
737 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 926 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
738 } 927 }
739 return false; 928 m_items.LockItemsForWrite(false);
740 929
930 return false;
741 } 931 }
742 932
743 /// <summary> 933 /// <summary>
@@ -748,43 +938,59 @@ namespace OpenSim.Region.Framework.Scenes
748 /// in this prim's inventory.</returns> 938 /// in this prim's inventory.</returns>
749 public int RemoveInventoryItem(UUID itemID) 939 public int RemoveInventoryItem(UUID itemID)
750 { 940 {
751 TaskInventoryItem item = GetInventoryItem(itemID); 941 m_items.LockItemsForRead(true);
752 if (item != null) 942
943 if (m_items.ContainsKey(itemID))
753 { 944 {
754 int type = m_items[itemID].InvType; 945 int type = m_items[itemID].InvType;
946 m_items.LockItemsForRead(false);
755 if (type == 10) // Script 947 if (type == 10) // Script
756 { 948 {
757 m_part.RemoveScriptEvents(itemID);
758 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 949 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
759 } 950 }
951 m_items.LockItemsForWrite(true);
760 m_items.Remove(itemID); 952 m_items.Remove(itemID);
953 m_items.LockItemsForWrite(false);
761 m_inventorySerial++; 954 m_inventorySerial++;
762 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 955 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
763 956
764 HasInventoryChanged = true; 957 HasInventoryChanged = true;
765 m_part.ParentGroup.HasGroupChanged = true; 958 m_part.ParentGroup.HasGroupChanged = true;
766 959
767 if (!ContainsScripts()) 960 int scriptcount = 0;
961 m_items.LockItemsForRead(true);
962 foreach (TaskInventoryItem item in m_items.Values)
963 {
964 if (item.Type == 10)
965 {
966 scriptcount++;
967 }
968 }
969 m_items.LockItemsForRead(false);
970
971
972 if (scriptcount <= 0)
973 {
768 m_part.RemFlag(PrimFlags.Scripted); 974 m_part.RemFlag(PrimFlags.Scripted);
975 }
769 976
770 m_part.ScheduleFullUpdate(); 977 m_part.ScheduleFullUpdate();
771 978
772 return type; 979 return type;
773
774 } 980 }
775 else 981 else
776 { 982 {
983 m_items.LockItemsForRead(false);
777 m_log.ErrorFormat( 984 m_log.ErrorFormat(
778 "[PRIM INVENTORY]: " + 985 "[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", 986 "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, 987 itemID, m_part.Name, m_part.UUID);
781 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
782 } 988 }
783 989
784 return -1; 990 return -1;
785 } 991 }
786 992
787 private bool CreateInventoryFile() 993 private bool CreateInventoryFileName()
788 { 994 {
789// m_log.DebugFormat( 995// m_log.DebugFormat(
790// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 996// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -793,116 +999,125 @@ namespace OpenSim.Region.Framework.Scenes
793 if (m_inventoryFileName == String.Empty || 999 if (m_inventoryFileName == String.Empty ||
794 m_inventoryFileNameSerial < m_inventorySerial) 1000 m_inventoryFileNameSerial < m_inventorySerial)
795 { 1001 {
796 // Something changed, we need to create a new file
797 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 1002 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
798 m_inventoryFileNameSerial = m_inventorySerial; 1003 m_inventoryFileNameSerial = m_inventorySerial;
799 1004
800 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1005 return true;
1006 }
1007
1008 return false;
1009 }
1010
1011 /// <summary>
1012 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1013 /// </summary>
1014 /// <param name="xferManager"></param>
1015 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1016 {
1017 bool changed = CreateInventoryFileName();
1018
1019 bool includeAssets = false;
1020 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1021 includeAssets = true;
1022
1023 if (m_inventoryPrivileged != includeAssets)
1024 changed = true;
1025
1026 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1027
1028 Items.LockItemsForRead(true);
1029
1030 if (m_inventorySerial == 0) // No inventory
1031 {
1032 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1033 Items.LockItemsForRead(false);
1034 return;
1035 }
801 1036
802 lock (m_items) 1037 if (m_items.Count == 0) // No inventory
1038 {
1039 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1040 Items.LockItemsForRead(false);
1041 return;
1042 }
1043
1044 if (!changed)
1045 {
1046 if (m_inventoryFileData.Length > 2)
803 { 1047 {
804 foreach (TaskInventoryItem item in m_items.Values) 1048 xferManager.AddNewFile(m_inventoryFileName,
805 { 1049 m_inventoryFileData);
806// m_log.DebugFormat( 1050 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
807// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1051 Util.StringToBytes256(m_inventoryFileName));
808// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
809 1052
810 UUID ownerID = item.OwnerID; 1053 Items.LockItemsForRead(false);
811 uint everyoneMask = 0; 1054 return;
812 uint baseMask = item.BasePermissions; 1055 }
813 uint ownerMask = item.CurrentPermissions; 1056 }
814 uint groupMask = item.GroupPermissions;
815 1057
816 invString.AddItemStart(); 1058 m_inventoryPrivileged = includeAssets;
817 invString.AddNameValueLine("item_id", item.ItemID.ToString());
818 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
819 1059
820 invString.AddPermissionsStart(); 1060 foreach (TaskInventoryItem item in m_items.Values)
1061 {
1062 UUID ownerID = item.OwnerID;
1063 uint everyoneMask = 0;
1064 uint baseMask = item.BasePermissions;
1065 uint ownerMask = item.CurrentPermissions;
1066 uint groupMask = item.GroupPermissions;
821 1067
822 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1068 invString.AddItemStart();
823 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1069 invString.AddNameValueLine("item_id", item.ItemID.ToString());
824 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1070 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 1071
828 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1072 invString.AddPermissionsStart();
829 invString.AddNameValueLine("owner_id", ownerID.ToString());
830 1073
831 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1074 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1075 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1076 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1077 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1078 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
832 1079
833 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1080 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
834 invString.AddSectionEnd(); 1081 invString.AddNameValueLine("owner_id", ownerID.ToString());
835 1082
836 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1083 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 1084
841 invString.AddSaleStart(); 1085 invString.AddNameValueLine("group_id", item.GroupID.ToString());
842 invString.AddNameValueLine("sale_type", "not"); 1086 invString.AddSectionEnd();
843 invString.AddNameValueLine("sale_price", "0");
844 invString.AddSectionEnd();
845 1087
846 invString.AddNameValueLine("name", item.Name + "|"); 1088 if (includeAssets)
847 invString.AddNameValueLine("desc", item.Description + "|"); 1089 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1090 else
1091 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1092 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1093 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1094 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
848 1095
849 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1096 invString.AddSaleStart();
850 invString.AddSectionEnd(); 1097 invString.AddNameValueLine("sale_type", "not");
851 } 1098 invString.AddNameValueLine("sale_price", "0");
852 } 1099 invString.AddSectionEnd();
853 1100
854 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1101 invString.AddNameValueLine("name", item.Name + "|");
1102 invString.AddNameValueLine("desc", item.Description + "|");
855 1103
856 return true; 1104 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1105 invString.AddSectionEnd();
857 } 1106 }
858 1107
859 // No need to recreate, the existing file is fine 1108 Items.LockItemsForRead(false);
860 return false;
861 }
862
863 /// <summary>
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 1109
879 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1110 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
880 return;
881 }
882 1111
883 CreateInventoryFile(); 1112 if (m_inventoryFileData.Length > 2)
884 1113 {
885 // In principle, we should only do the rest if the inventory changed; 1114 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
886 // by sending m_inventorySerial to the client, it ought to know 1115 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
887 // that nothing changed and that it doesn't need to request the file. 1116 Util.StringToBytes256(m_inventoryFileName));
888 // Unfortunately, it doesn't look like the client optimizes this; 1117 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 } 1118 }
1119
1120 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
906 } 1121 }
907 1122
908 /// <summary> 1123 /// <summary>
@@ -911,13 +1126,19 @@ namespace OpenSim.Region.Framework.Scenes
911 /// <param name="datastore"></param> 1126 /// <param name="datastore"></param>
912 public void ProcessInventoryBackup(ISimulationDataService datastore) 1127 public void ProcessInventoryBackup(ISimulationDataService datastore)
913 { 1128 {
914 if (HasInventoryChanged) 1129// Removed this because linking will cause an immediate delete of the new
915 { 1130// child prim from the database and the subsequent storing of the prim sees
916 HasInventoryChanged = false; 1131// the inventory of it as unchanged and doesn't store it at all. The overhead
917 List<TaskInventoryItem> items = GetInventoryItems(); 1132// of storing prim inventory needlessly is much less than the aggravation
918 datastore.StorePrimInventory(m_part.UUID, items); 1133// of prim inventory loss.
1134// if (HasInventoryChanged)
1135// {
1136 Items.LockItemsForRead(true);
1137 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1138 Items.LockItemsForRead(false);
919 1139
920 } 1140 HasInventoryChanged = false;
1141// }
921 } 1142 }
922 1143
923 public class InventoryStringBuilder 1144 public class InventoryStringBuilder
@@ -983,82 +1204,63 @@ namespace OpenSim.Region.Framework.Scenes
983 { 1204 {
984 uint mask=0x7fffffff; 1205 uint mask=0x7fffffff;
985 1206
986 lock (m_items) 1207 foreach (TaskInventoryItem item in m_items.Values)
987 { 1208 {
988 foreach (TaskInventoryItem item in m_items.Values) 1209 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1210 mask &= ~((uint)PermissionMask.Copy >> 13);
1211 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1212 mask &= ~((uint)PermissionMask.Transfer >> 13);
1213 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1214 mask &= ~((uint)PermissionMask.Modify >> 13);
1215
1216 if (item.InvType == (int)InventoryType.Object)
989 { 1217 {
990 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1218 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
991 mask &= ~((uint)PermissionMask.Copy >> 13); 1219 mask &= ~((uint)PermissionMask.Copy >> 13);
992 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1220 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
993 mask &= ~((uint)PermissionMask.Transfer >> 13); 1221 mask &= ~((uint)PermissionMask.Transfer >> 13);
994 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1222 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
995 mask &= ~((uint)PermissionMask.Modify >> 13); 1223 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 } 1224 }
1225
1226 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1227 mask &= ~(uint)PermissionMask.Copy;
1228 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1229 mask &= ~(uint)PermissionMask.Transfer;
1230 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1231 mask &= ~(uint)PermissionMask.Modify;
1023 } 1232 }
1024
1025 return mask; 1233 return mask;
1026 } 1234 }
1027 1235
1028 public void ApplyNextOwnerPermissions() 1236 public void ApplyNextOwnerPermissions()
1029 { 1237 {
1030 lock (m_items) 1238 foreach (TaskInventoryItem item in m_items.Values)
1031 { 1239 {
1032 foreach (TaskInventoryItem item in m_items.Values) 1240 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1033 { 1241 {
1034 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1242 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1035 { 1243 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1036 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1244 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1037 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1245 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1038 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1246 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1039 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1247 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 } 1248 }
1249 item.OwnerChanged = true;
1250 item.CurrentPermissions &= item.NextPermissions;
1251 item.BasePermissions &= item.NextPermissions;
1252 item.EveryonePermissions &= item.NextPermissions;
1253 item.PermsMask = 0;
1254 item.PermsGranter = UUID.Zero;
1050 } 1255 }
1051 } 1256 }
1052 1257
1053 public void ApplyGodPermissions(uint perms) 1258 public void ApplyGodPermissions(uint perms)
1054 { 1259 {
1055 lock (m_items) 1260 foreach (TaskInventoryItem item in m_items.Values)
1056 { 1261 {
1057 foreach (TaskInventoryItem item in m_items.Values) 1262 item.CurrentPermissions = perms;
1058 { 1263 item.BasePermissions = perms;
1059 item.CurrentPermissions = perms;
1060 item.BasePermissions = perms;
1061 }
1062 } 1264 }
1063 1265
1064 m_inventorySerial++; 1266 m_inventorySerial++;
@@ -1071,17 +1273,13 @@ namespace OpenSim.Region.Framework.Scenes
1071 /// <returns></returns> 1273 /// <returns></returns>
1072 public bool ContainsScripts() 1274 public bool ContainsScripts()
1073 { 1275 {
1074 lock (m_items) 1276 foreach (TaskInventoryItem item in m_items.Values)
1075 { 1277 {
1076 foreach (TaskInventoryItem item in m_items.Values) 1278 if (item.InvType == (int)InventoryType.LSL)
1077 { 1279 {
1078 if (item.InvType == (int)InventoryType.LSL) 1280 return true;
1079 {
1080 return true;
1081 }
1082 } 1281 }
1083 } 1282 }
1084
1085 return false; 1283 return false;
1086 } 1284 }
1087 1285
@@ -1089,11 +1287,8 @@ namespace OpenSim.Region.Framework.Scenes
1089 { 1287 {
1090 List<UUID> ret = new List<UUID>(); 1288 List<UUID> ret = new List<UUID>();
1091 1289
1092 lock (m_items) 1290 foreach (TaskInventoryItem item in m_items.Values)
1093 { 1291 ret.Add(item.ItemID);
1094 foreach (TaskInventoryItem item in m_items.Values)
1095 ret.Add(item.ItemID);
1096 }
1097 1292
1098 return ret; 1293 return ret;
1099 } 1294 }
@@ -1124,6 +1319,11 @@ namespace OpenSim.Region.Framework.Scenes
1124 1319
1125 public Dictionary<UUID, string> GetScriptStates() 1320 public Dictionary<UUID, string> GetScriptStates()
1126 { 1321 {
1322 return GetScriptStates(false);
1323 }
1324
1325 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1326 {
1127 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1327 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1128 1328
1129 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1329 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1134,25 +1334,35 @@ namespace OpenSim.Region.Framework.Scenes
1134 if (engines.Length == 0) // No engine at all 1334 if (engines.Length == 0) // No engine at all
1135 return ret; 1335 return ret;
1136 1336
1137 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1337 Items.LockItemsForRead(true);
1138 1338 foreach (TaskInventoryItem item in m_items.Values)
1139 foreach (TaskInventoryItem item in scripts)
1140 { 1339 {
1141 foreach (IScriptModule e in engines) 1340 if (item.InvType == (int)InventoryType.LSL)
1142 { 1341 {
1143 if (e != null) 1342 foreach (IScriptModule e in engines)
1144 { 1343 {
1145 string n = e.GetXMLState(item.ItemID); 1344 if (e != null)
1146 if (n != String.Empty)
1147 { 1345 {
1148 if (!ret.ContainsKey(item.ItemID)) 1346 string n = e.GetXMLState(item.ItemID);
1149 ret[item.ItemID] = n; 1347 if (n != String.Empty)
1150 break; 1348 {
1349 if (oldIDs)
1350 {
1351 if (!ret.ContainsKey(item.OldItemID))
1352 ret[item.OldItemID] = n;
1353 }
1354 else
1355 {
1356 if (!ret.ContainsKey(item.ItemID))
1357 ret[item.ItemID] = n;
1358 }
1359 break;
1360 }
1151 } 1361 }
1152 } 1362 }
1153 } 1363 }
1154 } 1364 }
1155 1365 Items.LockItemsForRead(false);
1156 return ret; 1366 return ret;
1157 } 1367 }
1158 1368
@@ -1162,21 +1372,27 @@ namespace OpenSim.Region.Framework.Scenes
1162 if (engines.Length == 0) 1372 if (engines.Length == 0)
1163 return; 1373 return;
1164 1374
1165 List<TaskInventoryItem> scripts = GetInventoryScripts();
1166 1375
1167 foreach (TaskInventoryItem item in scripts) 1376 Items.LockItemsForRead(true);
1377
1378 foreach (TaskInventoryItem item in m_items.Values)
1168 { 1379 {
1169 foreach (IScriptModule engine in engines) 1380 if (item.InvType == (int)InventoryType.LSL)
1170 { 1381 {
1171 if (engine != null) 1382 foreach (IScriptModule engine in engines)
1172 { 1383 {
1173 if (item.OwnerChanged) 1384 if (engine != null)
1174 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1385 {
1175 item.OwnerChanged = false; 1386 if (item.OwnerChanged)
1176 engine.ResumeScript(item.ItemID); 1387 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1388 item.OwnerChanged = false;
1389 engine.ResumeScript(item.ItemID);
1390 }
1177 } 1391 }
1178 } 1392 }
1179 } 1393 }
1394
1395 Items.LockItemsForRead(false);
1180 } 1396 }
1181 } 1397 }
1182} 1398}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index b84660a..c4aaebe 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -91,7 +91,7 @@ namespace OpenSim.Region.Framework.Scenes
91 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 91 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
92 /// issue #1716 92 /// issue #1716
93 /// </summary> 93 /// </summary>
94 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); 94 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
95 95
96 /// <summary> 96 /// <summary>
97 /// Movement updates for agents in neighboring regions are sent directly to clients. 97 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -168,6 +168,7 @@ namespace OpenSim.Region.Framework.Scenes
168// private int m_lastColCount = -1; //KF: Look for Collision chnages 168// private int m_lastColCount = -1; //KF: Look for Collision chnages
169// private int m_updateCount = 0; //KF: Update Anims for a while 169// private int m_updateCount = 0; //KF: Update Anims for a while
170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
171 private List<uint> m_lastColliders = new List<uint>();
171 172
172 private TeleportFlags m_teleportFlags; 173 private TeleportFlags m_teleportFlags;
173 public TeleportFlags TeleportFlags 174 public TeleportFlags TeleportFlags
@@ -229,6 +230,11 @@ namespace OpenSim.Region.Framework.Scenes
229 //private int m_moveToPositionStateStatus; 230 //private int m_moveToPositionStateStatus;
230 //***************************************************** 231 //*****************************************************
231 232
233 private bool m_collisionEventFlag = false;
234 private object m_collisionEventLock = new Object();
235
236 private Vector3 m_prevSitOffset;
237
232 protected AvatarAppearance m_appearance; 238 protected AvatarAppearance m_appearance;
233 239
234 public AvatarAppearance Appearance 240 public AvatarAppearance Appearance
@@ -568,6 +574,13 @@ namespace OpenSim.Region.Framework.Scenes
568 /// </summary> 574 /// </summary>
569 public uint ParentID { get; set; } 575 public uint ParentID { get; set; }
570 576
577 public UUID ParentUUID
578 {
579 get { return m_parentUUID; }
580 set { m_parentUUID = value; }
581 }
582 private UUID m_parentUUID = UUID.Zero;
583
571 /// <summary> 584 /// <summary>
572 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null. 585 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
573 /// </summary> 586 /// </summary>
@@ -797,10 +810,38 @@ namespace OpenSim.Region.Framework.Scenes
797 "[SCENE]: Upgrading child to root agent for {0} in {1}", 810 "[SCENE]: Upgrading child to root agent for {0} in {1}",
798 Name, m_scene.RegionInfo.RegionName); 811 Name, m_scene.RegionInfo.RegionName);
799 812
800 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
801
802 bool wasChild = IsChildAgent; 813 bool wasChild = IsChildAgent;
803 IsChildAgent = false; 814
815 if (ParentUUID != UUID.Zero)
816 {
817 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
818 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
819 if (part == null)
820 {
821 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
822 }
823 else
824 {
825 part.ParentGroup.AddAvatar(UUID);
826 if (part.SitTargetPosition != Vector3.Zero)
827 part.SitTargetAvatar = UUID;
828 ParentPosition = part.GetWorldPosition();
829 ParentID = part.LocalId;
830 ParentPart = part;
831 m_pos = m_prevSitOffset;
832 pos = ParentPosition;
833 }
834 ParentUUID = UUID.Zero;
835
836 IsChildAgent = false;
837
838 Animator.TrySetMovementAnimation("SIT");
839 }
840 else
841 {
842 IsChildAgent = false;
843 }
844
804 845
805 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 846 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
806 if (gm != null) 847 if (gm != null)
@@ -810,62 +851,64 @@ namespace OpenSim.Region.Framework.Scenes
810 851
811 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 852 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
812 853
813 // Moved this from SendInitialData to ensure that Appearance is initialized 854 if (ParentID == 0)
814 // before the inventory is processed in MakeRootAgent. This fixes a race condition
815 // related to the handling of attachments
816 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
817 if (m_scene.TestBorderCross(pos, Cardinals.E))
818 { 855 {
819 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 856 // Moved this from SendInitialData to ensure that Appearance is initialized
820 pos.X = crossedBorder.BorderLine.Z - 1; 857 // before the inventory is processed in MakeRootAgent. This fixes a race condition
821 } 858 // related to the handling of attachments
859 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
860 if (m_scene.TestBorderCross(pos, Cardinals.E))
861 {
862 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
863 pos.X = crossedBorder.BorderLine.Z - 1;
864 }
822 865
823 if (m_scene.TestBorderCross(pos, Cardinals.N)) 866 if (m_scene.TestBorderCross(pos, Cardinals.N))
824 { 867 {
825 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 868 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
826 pos.Y = crossedBorder.BorderLine.Z - 1; 869 pos.Y = crossedBorder.BorderLine.Z - 1;
827 } 870 }
828 871
829 CheckAndAdjustLandingPoint(ref pos); 872 CheckAndAdjustLandingPoint(ref pos);
830 873
831 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 874 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
832 { 875 {
833 m_log.WarnFormat( 876 m_log.WarnFormat(
834 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 877 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
835 pos, Name, UUID); 878 pos, Name, UUID);
836 879
837 if (pos.X < 0f) pos.X = 0f; 880 if (pos.X < 0f) pos.X = 0f;
838 if (pos.Y < 0f) pos.Y = 0f; 881 if (pos.Y < 0f) pos.Y = 0f;
839 if (pos.Z < 0f) pos.Z = 0f; 882 if (pos.Z < 0f) pos.Z = 0f;
840 } 883 }
841 884
842 float localAVHeight = 1.56f; 885 float localAVHeight = 1.56f;
843 if (Appearance.AvatarHeight > 0) 886 if (Appearance.AvatarHeight > 0)
844 localAVHeight = Appearance.AvatarHeight; 887 localAVHeight = Appearance.AvatarHeight;
845 888
846 float posZLimit = 0; 889 float posZLimit = 0;
847 890
848 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 891 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
849 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 892 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
850 893
851 float newPosZ = posZLimit + localAVHeight / 2; 894 float newPosZ = posZLimit + localAVHeight / 2;
852 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 895 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
853 { 896 {
854 pos.Z = newPosZ; 897 pos.Z = newPosZ;
855 } 898 }
856 AbsolutePosition = pos; 899 AbsolutePosition = pos;
857 900
858 AddToPhysicalScene(isFlying); 901 AddToPhysicalScene(isFlying);
859 902
860 if (ForceFly) 903 if (ForceFly)
861 { 904 {
862 Flying = true; 905 Flying = true;
863 } 906 }
864 else if (FlyDisabled) 907 else if (FlyDisabled)
865 { 908 {
866 Flying = false; 909 Flying = false;
910 }
867 } 911 }
868
869 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 912 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
870 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 913 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
871 // elsewhere anyway 914 // elsewhere anyway
@@ -883,14 +926,19 @@ namespace OpenSim.Region.Framework.Scenes
883 { 926 {
884 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 927 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
885 // Resume scripts 928 // Resume scripts
886 foreach (SceneObjectGroup sog in m_attachments) 929 Util.FireAndForget(delegate(object x) {
887 { 930 foreach (SceneObjectGroup sog in m_attachments)
888 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 931 {
889 sog.ResumeScripts(); 932 sog.ScheduleGroupForFullUpdate();
890 } 933 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
934 sog.ResumeScripts();
935 }
936 });
891 } 937 }
892 } 938 }
893 939
940 SendAvatarDataToAllAgents();
941
894 // send the animations of the other presences to me 942 // send the animations of the other presences to me
895 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) 943 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
896 { 944 {
@@ -1687,9 +1735,9 @@ namespace OpenSim.Region.Framework.Scenes
1687 if (pos.Z - terrainHeight < 0.2) 1735 if (pos.Z - terrainHeight < 0.2)
1688 pos.Z = terrainHeight; 1736 pos.Z = terrainHeight;
1689 1737
1690 m_log.DebugFormat( 1738// m_log.DebugFormat(
1691 "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 1739// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
1692 Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 1740// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
1693 1741
1694 if (noFly) 1742 if (noFly)
1695 Flying = false; 1743 Flying = false;
@@ -1746,8 +1794,11 @@ namespace OpenSim.Region.Framework.Scenes
1746// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 1794// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
1747 1795
1748 SitGround = false; 1796 SitGround = false;
1797
1798/* move this down so avatar gets physical in the new position and not where it is siting
1749 if (PhysicsActor == null) 1799 if (PhysicsActor == null)
1750 AddToPhysicalScene(false); 1800 AddToPhysicalScene(false);
1801 */
1751 1802
1752 if (ParentID != 0) 1803 if (ParentID != 0)
1753 { 1804 {
@@ -1771,6 +1822,7 @@ namespace OpenSim.Region.Framework.Scenes
1771 if (part.SitTargetAvatar == UUID) 1822 if (part.SitTargetAvatar == UUID)
1772 part.SitTargetAvatar = UUID.Zero; 1823 part.SitTargetAvatar = UUID.Zero;
1773 1824
1825 part.ParentGroup.DeleteAvatar(UUID);
1774 ParentPosition = part.GetWorldPosition(); 1826 ParentPosition = part.GetWorldPosition();
1775 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1827 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1776 1828
@@ -1779,6 +1831,10 @@ namespace OpenSim.Region.Framework.Scenes
1779 1831
1780 ParentID = 0; 1832 ParentID = 0;
1781 ParentPart = null; 1833 ParentPart = null;
1834
1835 if (PhysicsActor == null)
1836 AddToPhysicalScene(false);
1837
1782 SendAvatarDataToAllAgents(); 1838 SendAvatarDataToAllAgents();
1783 m_requestedSitTargetID = 0; 1839 m_requestedSitTargetID = 0;
1784 1840
@@ -1786,6 +1842,9 @@ namespace OpenSim.Region.Framework.Scenes
1786 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 1842 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1787 } 1843 }
1788 1844
1845 else if (PhysicsActor == null)
1846 AddToPhysicalScene(false);
1847
1789 Animator.TrySetMovementAnimation("STAND"); 1848 Animator.TrySetMovementAnimation("STAND");
1790 } 1849 }
1791 1850
@@ -1909,7 +1968,7 @@ namespace OpenSim.Region.Framework.Scenes
1909 forceMouselook = part.GetForceMouselook(); 1968 forceMouselook = part.GetForceMouselook();
1910 1969
1911 ControllingClient.SendSitResponse( 1970 ControllingClient.SendSitResponse(
1912 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 1971 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1913 1972
1914 m_requestedSitTargetUUID = targetID; 1973 m_requestedSitTargetUUID = targetID;
1915 1974
@@ -2191,14 +2250,36 @@ namespace OpenSim.Region.Framework.Scenes
2191 2250
2192 //Quaternion result = (sitTargetOrient * vq) * nq; 2251 //Quaternion result = (sitTargetOrient * vq) * nq;
2193 2252
2194 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2253 double x, y, z, m;
2254
2255 Quaternion r = sitTargetOrient;
2256 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2257
2258 if (Math.Abs(1.0 - m) > 0.000001)
2259 {
2260 m = 1.0 / Math.Sqrt(m);
2261 r.X *= (float)m;
2262 r.Y *= (float)m;
2263 r.Z *= (float)m;
2264 r.W *= (float)m;
2265 }
2266
2267 x = 2 * (r.X * r.Z + r.Y * r.W);
2268 y = 2 * (-r.X * r.W + r.Y * r.Z);
2269 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2270
2271 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2272 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2273 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2195 Rotation = sitTargetOrient; 2274 Rotation = sitTargetOrient;
2196 ParentPosition = part.AbsolutePosition; 2275 ParentPosition = part.AbsolutePosition;
2276 part.ParentGroup.AddAvatar(UUID);
2197 } 2277 }
2198 else 2278 else
2199 { 2279 {
2200 m_pos -= part.AbsolutePosition; 2280 m_pos -= part.AbsolutePosition;
2201 ParentPosition = part.AbsolutePosition; 2281 ParentPosition = part.AbsolutePosition;
2282 part.ParentGroup.AddAvatar(UUID);
2202 2283
2203// m_log.DebugFormat( 2284// m_log.DebugFormat(
2204// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2285// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -3037,6 +3118,9 @@ namespace OpenSim.Region.Framework.Scenes
3037 cAgent.AlwaysRun = SetAlwaysRun; 3118 cAgent.AlwaysRun = SetAlwaysRun;
3038 3119
3039 cAgent.Appearance = new AvatarAppearance(Appearance); 3120 cAgent.Appearance = new AvatarAppearance(Appearance);
3121
3122 cAgent.ParentPart = ParentUUID;
3123 cAgent.SitOffset = m_pos;
3040 3124
3041 lock (scriptedcontrols) 3125 lock (scriptedcontrols)
3042 { 3126 {
@@ -3096,6 +3180,8 @@ namespace OpenSim.Region.Framework.Scenes
3096 CameraAtAxis = cAgent.AtAxis; 3180 CameraAtAxis = cAgent.AtAxis;
3097 CameraLeftAxis = cAgent.LeftAxis; 3181 CameraLeftAxis = cAgent.LeftAxis;
3098 CameraUpAxis = cAgent.UpAxis; 3182 CameraUpAxis = cAgent.UpAxis;
3183 ParentUUID = cAgent.ParentPart;
3184 m_prevSitOffset = cAgent.SitOffset;
3099 3185
3100 // When we get to the point of re-computing neighbors everytime this 3186 // When we get to the point of re-computing neighbors everytime this
3101 // changes, then start using the agent's drawdistance rather than the 3187 // changes, then start using the agent's drawdistance rather than the
@@ -3302,6 +3388,8 @@ namespace OpenSim.Region.Framework.Scenes
3302 } 3388 }
3303 } 3389 }
3304 3390
3391 RaiseCollisionScriptEvents(coldata);
3392
3305 if (Invulnerable) 3393 if (Invulnerable)
3306 return; 3394 return;
3307 3395
@@ -3813,6 +3901,12 @@ namespace OpenSim.Region.Framework.Scenes
3813 3901
3814 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 3902 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3815 { 3903 {
3904 string reason;
3905
3906 // Honor bans
3907 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
3908 return;
3909
3816 SceneObjectGroup telehub = null; 3910 SceneObjectGroup telehub = null;
3817 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 3911 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
3818 { 3912 {
@@ -3852,11 +3946,173 @@ namespace OpenSim.Region.Framework.Scenes
3852 pos = land.LandData.UserLocation; 3946 pos = land.LandData.UserLocation;
3853 } 3947 }
3854 } 3948 }
3855 3949
3856 land.SendLandUpdateToClient(ControllingClient); 3950 land.SendLandUpdateToClient(ControllingClient);
3857 } 3951 }
3858 } 3952 }
3859 3953
3954 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
3955 {
3956 lock(m_collisionEventLock)
3957 {
3958 if (m_collisionEventFlag)
3959 return;
3960 m_collisionEventFlag = true;
3961 }
3962
3963 Util.FireAndForget(delegate(object x)
3964 {
3965 try
3966 {
3967 List<uint> thisHitColliders = new List<uint>();
3968 List<uint> endedColliders = new List<uint>();
3969 List<uint> startedColliders = new List<uint>();
3970
3971 foreach (uint localid in coldata.Keys)
3972 {
3973 thisHitColliders.Add(localid);
3974 if (!m_lastColliders.Contains(localid))
3975 {
3976 startedColliders.Add(localid);
3977 }
3978 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3979 }
3980
3981 // calculate things that ended colliding
3982 foreach (uint localID in m_lastColliders)
3983 {
3984 if (!thisHitColliders.Contains(localID))
3985 {
3986 endedColliders.Add(localID);
3987 }
3988 }
3989 //add the items that started colliding this time to the last colliders list.
3990 foreach (uint localID in startedColliders)
3991 {
3992 m_lastColliders.Add(localID);
3993 }
3994 // remove things that ended colliding from the last colliders list
3995 foreach (uint localID in endedColliders)
3996 {
3997 m_lastColliders.Remove(localID);
3998 }
3999
4000 // do event notification
4001 if (startedColliders.Count > 0)
4002 {
4003 ColliderArgs StartCollidingMessage = new ColliderArgs();
4004 List<DetectedObject> colliding = new List<DetectedObject>();
4005 foreach (uint localId in startedColliders)
4006 {
4007 if (localId == 0)
4008 continue;
4009
4010 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4011 string data = "";
4012 if (obj != null)
4013 {
4014 DetectedObject detobj = new DetectedObject();
4015 detobj.keyUUID = obj.UUID;
4016 detobj.nameStr = obj.Name;
4017 detobj.ownerUUID = obj.OwnerID;
4018 detobj.posVector = obj.AbsolutePosition;
4019 detobj.rotQuat = obj.GetWorldRotation();
4020 detobj.velVector = obj.Velocity;
4021 detobj.colliderType = 0;
4022 detobj.groupUUID = obj.GroupID;
4023 colliding.Add(detobj);
4024 }
4025 }
4026
4027 if (colliding.Count > 0)
4028 {
4029 StartCollidingMessage.Colliders = colliding;
4030
4031 foreach (SceneObjectGroup att in GetAttachments())
4032 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
4033 }
4034 }
4035
4036 if (endedColliders.Count > 0)
4037 {
4038 ColliderArgs EndCollidingMessage = new ColliderArgs();
4039 List<DetectedObject> colliding = new List<DetectedObject>();
4040 foreach (uint localId in endedColliders)
4041 {
4042 if (localId == 0)
4043 continue;
4044
4045 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4046 string data = "";
4047 if (obj != null)
4048 {
4049 DetectedObject detobj = new DetectedObject();
4050 detobj.keyUUID = obj.UUID;
4051 detobj.nameStr = obj.Name;
4052 detobj.ownerUUID = obj.OwnerID;
4053 detobj.posVector = obj.AbsolutePosition;
4054 detobj.rotQuat = obj.GetWorldRotation();
4055 detobj.velVector = obj.Velocity;
4056 detobj.colliderType = 0;
4057 detobj.groupUUID = obj.GroupID;
4058 colliding.Add(detobj);
4059 }
4060 }
4061
4062 if (colliding.Count > 0)
4063 {
4064 EndCollidingMessage.Colliders = colliding;
4065
4066 foreach (SceneObjectGroup att in GetAttachments())
4067 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4068 }
4069 }
4070
4071 if (thisHitColliders.Count > 0)
4072 {
4073 ColliderArgs CollidingMessage = new ColliderArgs();
4074 List<DetectedObject> colliding = new List<DetectedObject>();
4075 foreach (uint localId in thisHitColliders)
4076 {
4077 if (localId == 0)
4078 continue;
4079
4080 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4081 string data = "";
4082 if (obj != null)
4083 {
4084 DetectedObject detobj = new DetectedObject();
4085 detobj.keyUUID = obj.UUID;
4086 detobj.nameStr = obj.Name;
4087 detobj.ownerUUID = obj.OwnerID;
4088 detobj.posVector = obj.AbsolutePosition;
4089 detobj.rotQuat = obj.GetWorldRotation();
4090 detobj.velVector = obj.Velocity;
4091 detobj.colliderType = 0;
4092 detobj.groupUUID = obj.GroupID;
4093 colliding.Add(detobj);
4094 }
4095 }
4096
4097 if (colliding.Count > 0)
4098 {
4099 CollidingMessage.Colliders = colliding;
4100
4101 lock (m_attachments)
4102 {
4103 foreach (SceneObjectGroup att in m_attachments)
4104 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4105 }
4106 }
4107 }
4108 }
4109 finally
4110 {
4111 m_collisionEventFlag = false;
4112 }
4113 });
4114 }
4115
3860 private void TeleportFlagsDebug() { 4116 private void TeleportFlagsDebug() {
3861 4117
3862 // Some temporary debugging help to show all the TeleportFlags we have... 4118 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -3881,6 +4137,5 @@ namespace OpenSim.Region.Framework.Scenes
3881 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4137 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
3882 4138
3883 } 4139 }
3884
3885 } 4140 }
3886} 4141}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index e6b88a3..51a3320 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,16 @@ 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 //Ubit comented until proper testing
363 m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle);
364
365
350 #endregion 366 #endregion
351 367
352 #region TaskInventoryXmlProcessors initialization 368 #region TaskInventoryXmlProcessors initialization
@@ -569,6 +585,24 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
569 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty); 585 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty);
570 } 586 }
571 587
588 private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader)
589 {
590 bool errors = false;
591 SOPVehicle _vehicle = new SOPVehicle();
592
593 _vehicle.FromXml2(reader, out errors);
594
595 if (errors)
596 {
597 obj.sopVehicle = null;
598 m_log.DebugFormat(
599 "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.",
600 obj.Name, obj.UUID);
601 }
602 else
603 obj.sopVehicle = _vehicle;
604 }
605
572 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) 606 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader)
573 { 607 {
574 List<string> errorNodeNames; 608 List<string> errorNodeNames;
@@ -733,6 +767,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
733 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 767 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
734 } 768 }
735 769
770 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
771 {
772 obj.Buoyancy = (float)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
773 }
774
775 private static void ProcessForce(SceneObjectPart obj, XmlTextReader reader)
776 {
777 obj.Force = Util.ReadVector(reader, "Force");
778 }
779 private static void ProcessTorque(SceneObjectPart obj, XmlTextReader reader)
780 {
781 obj.Torque = Util.ReadVector(reader, "Torque");
782 }
783
784 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
785 {
786 obj.VolumeDetectActive = Util.ReadBoolean(reader);
787 }
788
736 #endregion 789 #endregion
737 790
738 #region TaskInventoryXmlProcessors 791 #region TaskInventoryXmlProcessors
@@ -1120,6 +1173,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1120 }); 1173 });
1121 1174
1122 writer.WriteEndElement(); 1175 writer.WriteEndElement();
1176
1177 if (sog.RootPart.KeyframeMotion != null)
1178 {
1179 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1180
1181 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1182 writer.WriteBase64(data, 0, data.Length);
1183 writer.WriteEndElement();
1184 }
1185
1123 writer.WriteEndElement(); 1186 writer.WriteEndElement();
1124 } 1187 }
1125 1188
@@ -1218,6 +1281,17 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1218 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1281 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1219 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1282 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1220 1283
1284 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1285
1286 WriteVector(writer, "Force", sop.Force);
1287 WriteVector(writer, "Torque", sop.Torque);
1288
1289 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1290
1291 //Ubit comented until proper testing
1292 if (sop.sopVehicle != null)
1293 sop.sopVehicle.ToXml2(writer);
1294
1221 writer.WriteEndElement(); 1295 writer.WriteEndElement();
1222 } 1296 }
1223 1297
@@ -1487,12 +1561,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1487 { 1561 {
1488 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1562 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1489 1563
1490 if (reader.IsEmptyElement)
1491 {
1492 reader.Read();
1493 return tinv;
1494 }
1495
1496 reader.ReadStartElement(name, String.Empty); 1564 reader.ReadStartElement(name, String.Empty);
1497 1565
1498 while (reader.Name == "TaskInventoryItem") 1566 while (reader.Name == "TaskInventoryItem")
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..38474de 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -30,12 +30,27 @@ using System.Reflection;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
33using System;
33 34
34namespace OpenSim.Region.Framework.Scenes 35namespace OpenSim.Region.Framework.Scenes
35{ 36{
37 [Flags]
38 public enum UndoType
39 {
40 STATE_PRIM_POSITION = 1,
41 STATE_PRIM_ROTATION = 2,
42 STATE_PRIM_SCALE = 4,
43 STATE_PRIM_ALL = 7,
44 STATE_GROUP_POSITION = 8,
45 STATE_GROUP_ROTATION = 16,
46 STATE_GROUP_SCALE = 32,
47 STATE_GROUP_ALL = 56,
48 STATE_ALL = 63
49 }
50
36 public class UndoState 51 public class UndoState
37 { 52 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39 54
40 public Vector3 Position = Vector3.Zero; 55 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero; 56 public Vector3 Scale = Vector3.Zero;
@@ -51,43 +66,22 @@ namespace OpenSim.Region.Framework.Scenes
51 /// </summary> 66 /// </summary>
52 /// <param name="part"></param> 67 /// <param name="part"></param>
53 /// <param name="forGroup">True if the undo is for an entire group</param> 68 /// <param name="forGroup">True if the undo is for an entire group</param>
69 /// only for root parts ????
54 public UndoState(SceneObjectPart part, bool forGroup) 70 public UndoState(SceneObjectPart part, bool forGroup)
55 { 71 {
56 if (part.ParentID == 0) 72 if (part.ParentID == 0)
57 { 73 {
58 ForGroup = forGroup; 74 ForGroup = forGroup;
59 75 Position = part.ParentGroup.AbsolutePosition;
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
68 Rotation = part.RotationOffset; 76 Rotation = part.RotationOffset;
69
70// m_log.DebugFormat(
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation);
72
73 Scale = part.Shape.Scale; 77 Scale = part.Shape.Scale;
74
75// m_log.DebugFormat(
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 78 }
78 else 79 else
79 { 80 {
81 ForGroup = false; // only root parts can undo grp
80 Position = part.OffsetPosition; 82 Position = part.OffsetPosition;
81// m_log.DebugFormat(
82// "[UNDO STATE]: Storing undo position {0} for child part", Position);
83
84 Rotation = part.RotationOffset; 83 Rotation = part.RotationOffset;
85// m_log.DebugFormat(
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation);
87
88 Scale = part.Shape.Scale; 84 Scale = part.Shape.Scale;
89// m_log.DebugFormat(
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale);
91 } 85 }
92 } 86 }
93 87
@@ -96,35 +90,40 @@ namespace OpenSim.Region.Framework.Scenes
96 /// </summary> 90 /// </summary>
97 /// <param name="part"></param> 91 /// <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> 92 /// <returns>true if both the part's position, rotation and scale match those in this undo state. False otherwise.</returns>
99 public bool Compare(SceneObjectPart part) 93 public bool Compare(SceneObjectPart part, bool forgrp)
100 { 94 {
95 if (ForGroup != forgrp) // if diferent targets, then they are diferent
96 return false;
97
101 if (part != null) 98 if (part != null)
102 { 99 {
103 if (part.ParentID == 0) 100 if (part.ParentID == 0)
104 return 101 {
105 Position == part.ParentGroup.AbsolutePosition 102 // root part
106 && Rotation == part.RotationOffset 103 // grp position is same as part
107 && Scale == part.Shape.Scale; 104 if (Position != part.ParentGroup.AbsolutePosition)
105 return false;
106 if (Rotation != part.RotationOffset)
107 return false;
108 return Scale == part.Shape.Scale;
109 }
108 else 110 else
109 return 111 {
110 Position == part.OffsetPosition 112 return (Position == part.OffsetPosition
111 && Rotation == part.RotationOffset 113 && Rotation == part.RotationOffset
112 && Scale == part.Shape.Scale; 114 && Scale == part.Shape.Scale);
115 }
113 } 116 }
114 117
115 return false; 118 return false;
116 } 119 }
117 120
118 public void PlaybackState(SceneObjectPart part) 121 public void PlayState(SceneObjectPart part)
119 { 122 {
120 part.Undoing = true; 123 part.Undoing = true;
121 124
122 if (part.ParentID == 0) 125 if (part.ParentID == 0)
123 { 126 {
124// m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId);
127
128 if (Position != Vector3.Zero) 127 if (Position != Vector3.Zero)
129 { 128 {
130 if (ForGroup) 129 if (ForGroup)
@@ -133,10 +132,6 @@ namespace OpenSim.Region.Framework.Scenes
133 part.ParentGroup.UpdateRootPosition(Position); 132 part.ParentGroup.UpdateRootPosition(Position);
134 } 133 }
135 134
136// m_log.DebugFormat(
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}",
138// part.RotationOffset, Rotation, part.Name, part.LocalId);
139
140 if (ForGroup) 135 if (ForGroup)
141 part.UpdateRotation(Rotation); 136 part.UpdateRotation(Rotation);
142 else 137 else
@@ -144,86 +139,29 @@ namespace OpenSim.Region.Framework.Scenes
144 139
145 if (Scale != Vector3.Zero) 140 if (Scale != Vector3.Zero)
146 { 141 {
147// m_log.DebugFormat(
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}",
149// part.Shape.Scale, Scale, part.Name, part.LocalId);
150
151 if (ForGroup) 142 if (ForGroup)
152 part.ParentGroup.GroupResize(Scale); 143 part.ParentGroup.GroupResize(Scale);
153 else 144 else
154 part.Resize(Scale); 145 part.Resize(Scale);
155 } 146 }
156
157 part.ParentGroup.ScheduleGroupForTerseUpdate(); 147 part.ParentGroup.ScheduleGroupForTerseUpdate();
158 } 148 }
159 else 149 else
160 { 150 {
161 // Note: Updating these properties on sop automatically schedules an update if needed 151 if (ForGroup) // trap for group since seems parts can't do it
162 if (Position != Vector3.Zero) 152 return;
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
168 part.OffsetPosition = Position;
169 }
170
171// m_log.DebugFormat(
172// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}",
173// part.RotationOffset, Rotation, part.Name, part.LocalId);
174 153
154 // Note: Updating these properties on sop automatically schedules an update if needed
155 part.OffsetPosition = Position;
175 part.UpdateRotation(Rotation); 156 part.UpdateRotation(Rotation);
176
177 if (Scale != Vector3.Zero) 157 if (Scale != Vector3.Zero)
178 { 158 {
179// m_log.DebugFormat(
180// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}",
181// part.Shape.Scale, Scale, part.Name, part.LocalId);
182
183 part.Resize(Scale); 159 part.Resize(Scale);
184 } 160 }
185 } 161 }
186 162
187 part.Undoing = false; 163 part.Undoing = false;
188 } 164 }
189
190 public void PlayfwdState(SceneObjectPart part)
191 {
192 part.Undoing = true;
193
194 if (part.ParentID == 0)
195 {
196 if (Position != Vector3.Zero)
197 part.ParentGroup.AbsolutePosition = Position;
198
199 if (Rotation != Quaternion.Identity)
200 part.UpdateRotation(Rotation);
201
202 if (Scale != Vector3.Zero)
203 {
204 if (ForGroup)
205 part.ParentGroup.GroupResize(Scale);
206 else
207 part.Resize(Scale);
208 }
209
210 part.ParentGroup.ScheduleGroupForTerseUpdate();
211 }
212 else
213 {
214 // Note: Updating these properties on sop automatically schedules an update if needed
215 if (Position != Vector3.Zero)
216 part.OffsetPosition = Position;
217
218 if (Rotation != Quaternion.Identity)
219 part.UpdateRotation(Rotation);
220
221 if (Scale != Vector3.Zero)
222 part.Resize(Scale);
223 }
224
225 part.Undoing = false;
226 }
227 } 165 }
228 166
229 public class LandUndoState 167 public class LandUndoState
@@ -247,4 +185,4 @@ namespace OpenSim.Region.Framework.Scenes
247 m_terrainModule.UndoTerrain(m_terrainChannel); 185 m_terrainModule.UndoTerrain(m_terrainChannel);
248 } 186 }
249 } 187 }
250} \ No newline at end of file 188}
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;