aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs214
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs221
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs317
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs14
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs244
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs656
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs281
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs570
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs971
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs168
15 files changed, 2724 insertions, 998 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index a90e0f3..9c103cb 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -53,11 +53,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
53 { 53 {
54 get { return m_movementAnimation; } 54 get { return m_movementAnimation; }
55 } 55 }
56 protected string m_movementAnimation = "DEFAULT"; 56 // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist!
57 57 protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init.
58 private int m_animTickFall; 58 private int m_animTickFall;
59 private int m_animTickJump; 59// private int m_animTickJump;
60 60 public int m_animTickJump; // ScenePresence has to see this to control +Z force
61 public bool m_jumping = false; // Add for jumping
62 public float m_jumpVelocity = 0f; // Add for jumping
63 private int m_landing = 0; // Add for jumping
64 public bool m_falling = false; // Add for falling
65 private float m_fallHeight; // Add for falling
66
61 /// <value> 67 /// <value>
62 /// The scene presence that this animator applies to 68 /// The scene presence that this animator applies to
63 /// </value> 69 /// </value>
@@ -114,7 +120,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation
114 120
115 public void ResetAnimations() 121 public void ResetAnimations()
116 { 122 {
123Console.WriteLine("ResetA.............");
117 m_animations.Clear(); 124 m_animations.Clear();
125TrySetMovementAnimation("STAND");
118 } 126 }
119 127
120 /// <summary> 128 /// <summary>
@@ -123,8 +131,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
123 /// </summary> 131 /// </summary>
124 public void TrySetMovementAnimation(string anim) 132 public void TrySetMovementAnimation(string anim)
125 { 133 {
126 //m_log.DebugFormat("Updating movement animation to {0}", anim);
127
128 if (!m_scenePresence.IsChildAgent) 134 if (!m_scenePresence.IsChildAgent)
129 { 135 {
130 if (m_animations.TrySetDefaultAnimation( 136 if (m_animations.TrySetDefaultAnimation(
@@ -142,14 +148,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
142 /// </summary> 148 /// </summary>
143 public string GetMovementAnimation() 149 public string GetMovementAnimation()
144 { 150 {
145 const float FALL_DELAY = 0.33f; 151//Console.WriteLine("GMA-------"); //##
146 const float PREJUMP_DELAY = 0.25f; 152//#@ const float FALL_DELAY = 0.33f;
147 153 const float FALL_DELAY = 800f; //## mS
154//rm for jumping const float PREJUMP_DELAY = 0.25f;
155 const float PREJUMP_DELAY = 200f; // mS add for jumping
156 const float JUMP_PERIOD = 800f; // mS add for jumping
148 #region Inputs 157 #region Inputs
149 if (m_scenePresence.SitGround) 158
150 {
151 return "SIT_GROUND_CONSTRAINED";
152 }
153 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 159 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
154 PhysicsActor actor = m_scenePresence.PhysicsActor; 160 PhysicsActor actor = m_scenePresence.PhysicsActor;
155 161
@@ -159,11 +165,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
159 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 165 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
160 166
161 // Check control flags 167 // Check control flags
162 bool heldForward = 168 bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS);
163 (((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) || ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS)); 169 bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
164 bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; 170 bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
165 bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; 171 bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG);
166 bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
167 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 172 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
168 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 173 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
169 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 174 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -182,8 +187,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
182 187
183 // Is the avatar trying to move? 188 // Is the avatar trying to move?
184// bool moving = (move != Vector3.Zero); 189// bool moving = (move != Vector3.Zero);
185 bool jumping = m_animTickJump != 0; 190// rm for jumping bool jumping = m_animTickJump != 0;
186
187 #endregion Inputs 191 #endregion Inputs
188 192
189 #region Flying 193 #region Flying
@@ -192,6 +196,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
192 { 196 {
193 m_animTickFall = 0; 197 m_animTickFall = 0;
194 m_animTickJump = 0; 198 m_animTickJump = 0;
199 m_jumping = false; //add for jumping
200 m_falling = true; //add for falling
201 m_jumpVelocity = 0f; //add for jumping
202 actor.Selected = false; //add for jumping flag
203 m_fallHeight = actor.Position.Z; // save latest flying height
195 204
196 if (move.X != 0f || move.Y != 0f) 205 if (move.X != 0f || move.Y != 0f)
197 { 206 {
@@ -203,8 +212,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
203 } 212 }
204 else if (move.Z < 0f) 213 else if (move.Z < 0f)
205 { 214 {
206 if (actor != null && actor.IsColliding) 215 if (actor != null && actor.IsColliding)
216 { //##
217//Console.WriteLine("LAND FLYING"); // ##
207 return "LAND"; 218 return "LAND";
219 } //#
208 else 220 else
209 return "HOVER_DOWN"; 221 return "HOVER_DOWN";
210 } 222 }
@@ -218,19 +230,28 @@ namespace OpenSim.Region.Framework.Scenes.Animation
218 230
219 #region Falling/Floating/Landing 231 #region Falling/Floating/Landing
220 232
221 if (actor == null || !actor.IsColliding) 233// rm for jumping if (actor == null || !actor.IsColliding)
234 if ((actor == null || !actor.IsColliding) && !m_jumping) // add for jumping
222 { 235 {
223 float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 236// rm float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
237 float fallElapsed = (float)(Environment.TickCount - m_animTickFall); // add, in mS
224 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; 238 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
239//Console.WriteLine("falling t={0} v={1}", fallElapsed, fallVelocity); //##
240
241// rm for fall if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f))
242 if (!m_jumping && (fallVelocity < -3.0f) ) m_falling = true; // add for falling and jumping
225 243
226 if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f)) 244 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) // add for jumping
245 // not falling yet or going up
227 { 246 {
228 // Just started falling 247 // reset start of fall time
229 m_animTickFall = Environment.TickCount; 248 m_animTickFall = Environment.TickCount;
230 } 249 }
231 else if (!jumping && fallElapsed > FALL_DELAY) 250// else if (!jumping && fallElapsed > FALL_DELAY)
251 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.m_wasFlying)) // add for falling and jumping
232 { 252 {
233 // Falling long enough to trigger the animation 253 // Falling long enough to trigger the animation
254//Console.WriteLine("FALLDOWN"); //##
234 return "FALLDOWN"; 255 return "FALLDOWN";
235 } 256 }
236 257
@@ -239,22 +260,97 @@ namespace OpenSim.Region.Framework.Scenes.Animation
239 260
240 #endregion Falling/Floating/Landing 261 #endregion Falling/Floating/Landing
241 262
263
264 #region Jumping // section added for jumping...
265
266 int jumptime;
267 jumptime = Environment.TickCount - m_animTickJump;
268
269
270 if ((move.Z > 0f) && (!m_jumping))
271 {
272//Console.WriteLine("PJ {0}", jumptime); //##
273 // Start jumping, prejump
274 m_animTickFall = 0;
275 m_jumping = true;
276 m_falling = false;
277 actor.Selected = true; // borrowed for jmping flag
278 m_animTickJump = Environment.TickCount;
279 m_jumpVelocity = 0.35f;
280 return "PREJUMP";
281 }
282
283 if(m_jumping)
284 {
285 if ( (jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
286 {
287//Console.WriteLine("LA {0}", jumptime); //##
288 // end jumping
289 m_jumping = false;
290 m_falling = false;
291 actor.Selected = false; // borrowed for jumping flag
292 m_jumpVelocity = 0f;
293 m_animTickFall = Environment.TickCount;
294 return "LAND";
295 }
296 else if (jumptime > JUMP_PERIOD)
297 {
298//Console.WriteLine("JD {0}", jumptime); //##
299 // jump down
300 m_jumpVelocity = 0f;
301 return "JUMP";
302 }
303 else if (jumptime > PREJUMP_DELAY)
304 {
305//Console.WriteLine("JU {0}", jumptime); //##
306 // jump up
307 m_jumping = true;
308 m_jumpVelocity = 10f;
309 return "JUMP";
310 }
311 }
312
313 #endregion Jumping // end added section
314
242 #region Ground Movement 315 #region Ground Movement
243 316
244 if (m_movementAnimation == "FALLDOWN") 317 if (m_movementAnimation == "FALLDOWN")
245 { 318 {
319 m_falling = false;
246 m_animTickFall = Environment.TickCount; 320 m_animTickFall = Environment.TickCount;
247
248 // TODO: SOFT_LAND support 321 // TODO: SOFT_LAND support
249 return "LAND"; 322 float fallHeight = m_fallHeight - actor.Position.Z;
323//Console.WriteLine("Hit from {0}", fallHeight); //##
324 if (fallHeight > 15.0f) // add for falling
325 return "STANDUP";
326 else if (fallHeight > 8.0f) // add for falling
327 return "SOFT_LAND"; // add for falling
328 else // add for falling
329 return "LAND"; // add for falling
250 } 330 }
251 else if (m_movementAnimation == "LAND") 331// rm jumping float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
332// rm jumping if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY))
333// rm for landing return "LAND";
334 else if ((m_movementAnimation == "LAND") || (m_movementAnimation == "SOFT_LAND") || (m_movementAnimation == "STANDUP"))
252 { 335 {
253 float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 336 int landElapsed = Environment.TickCount - m_animTickFall; // add for jumping
254 if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) 337 int limit = 1000; // add for jumping
255 return "LAND"; 338 if(m_movementAnimation == "LAND") limit = 350; // add for jumping
256 } 339 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
257 340
341 if ((m_animTickFall != 0) && (landElapsed <= limit)) // add for jumping
342 {
343//Console.WriteLine("Lelapse {0}", m_movementAnimation); //##
344 return m_movementAnimation;
345 }
346 else
347 {
348//Console.WriteLine("end/STAND"); //##
349 m_fallHeight = actor.Position.Z; // save latest flying height
350 return "STAND";
351 }
352 }
353/* This section removed, replaced by jumping section
258 m_animTickFall = 0; 354 m_animTickFall = 0;
259 355
260 if (move.Z > 0f) 356 if (move.Z > 0f)
@@ -266,7 +362,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
266 m_animTickJump = Environment.TickCount; 362 m_animTickJump = Environment.TickCount;
267 return "PREJUMP"; 363 return "PREJUMP";
268 } 364 }
269 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) 365 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 800.0f)
270 { 366 {
271 // Start actual jump 367 // Start actual jump
272 if (m_animTickJump == -1) 368 if (m_animTickJump == -1)
@@ -284,29 +380,34 @@ namespace OpenSim.Region.Framework.Scenes.Animation
284 { 380 {
285 // Not jumping 381 // Not jumping
286 m_animTickJump = 0; 382 m_animTickJump = 0;
287 383 */
288 if (move.X != 0f || move.Y != 0f) 384 // next section moved outside paren. and realigned for jumping
289 { 385 if (move.X != 0f || move.Y != 0f)
290 // Walking / crouchwalking / running 386 {
291 if (move.Z < 0f) 387 m_fallHeight = actor.Position.Z; // save latest flying height
292 return "CROUCHWALK"; 388 m_falling = false; // Add for falling
293 else if (m_scenePresence.SetAlwaysRun) 389 // Walking / crouchwalking / running
294 return "RUN"; 390 if (move.Z < 0f)
295 else 391 return "CROUCHWALK";
296 return "WALK"; 392 else if (m_scenePresence.SetAlwaysRun)
297 } 393 return "RUN";
298 else 394 else
299 { 395 return "WALK";
300 // Not walking
301 if (move.Z < 0f)
302 return "CROUCH";
303 else
304 return "STAND";
305 }
306 } 396 }
307 397// rm for jumping else
398 else if (!m_jumping) // add for jumping
399 {
400 m_falling = false; // Add for falling
401 // Not walking
402 if (move.Z < 0f)
403 return "CROUCH";
404 else
405 return "STAND";
406 }
407 // end section realign for jumping
308 #endregion Ground Movement 408 #endregion Ground Movement
309 409
410 m_falling = false; // Add for falling
310 return m_movementAnimation; 411 return m_movementAnimation;
311 } 412 }
312 413
@@ -316,16 +417,15 @@ namespace OpenSim.Region.Framework.Scenes.Animation
316 public void UpdateMovementAnimations() 417 public void UpdateMovementAnimations()
317 { 418 {
318 m_movementAnimation = GetMovementAnimation(); 419 m_movementAnimation = GetMovementAnimation();
319 420/* if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
320 if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
321 { 421 {
322 // This was the previous behavior before PREJUMP 422 // This was the previous behavior before PREJUMP
323 TrySetMovementAnimation("JUMP"); 423 TrySetMovementAnimation("JUMP");
324 } 424 }
325 else 425 else
326 { 426 { removed for jumping */
327 TrySetMovementAnimation(m_movementAnimation); 427 TrySetMovementAnimation(m_movementAnimation);
328 } 428// rm for jumping }
329 } 429 }
330 430
331 public UUID[] GetAnimationArray() 431 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 64567db..a8d24fd 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,8 +104,15 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
107 foreach (SceneObjectGroup g in objectGroups) 109 foreach (SceneObjectGroup g in objectGroups)
110 {
111 killIDs.Add(g.LocalId);
108 g.DeleteGroupFromScene(false); 112 g.DeleteGroupFromScene(false);
113 }
114
115 m_scene.SendKillObject(killIDs);
109 } 116 }
110 } 117 }
111 118
@@ -137,7 +144,7 @@ namespace OpenSim.Region.Framework.Scenes
137 x = m_inventoryDeletes.Dequeue(); 144 x = m_inventoryDeletes.Dequeue();
138 145
139 m_log.DebugFormat( 146 m_log.DebugFormat(
140 "[ASYNC DELETER]: Sending object to user's inventory, {0} item(s) remaining.", left); 147 "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", left, x.action, x.objectGroups.Count);
141 148
142 try 149 try
143 { 150 {
@@ -177,4 +184,4 @@ namespace OpenSim.Region.Framework.Scenes
177 return false; 184 return false;
178 } 185 }
179 } 186 }
180} \ No newline at end of file 187}
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index c321a15..f24c53c 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;
@@ -757,6 +761,26 @@ namespace OpenSim.Region.Framework.Scenes
757 } 761 }
758 } 762 }
759 } 763 }
764 public void TriggerTerrainUpdate()
765 {
766 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
767 if (handlerTerrainUpdate != null)
768 {
769 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
770 {
771 try
772 {
773 d();
774 }
775 catch (Exception e)
776 {
777 m_log.ErrorFormat(
778 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
779 e.Message, e.StackTrace);
780 }
781 }
782 }
783 }
760 784
761 public void TriggerTerrainTick() 785 public void TriggerTerrainTick()
762 { 786 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 19f8180..c75f8ba 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -167,6 +167,7 @@ namespace OpenSim.Region.Framework.Scenes
167 167
168 private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) 168 private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
169 { 169 {
170 if (entity == null) return double.NaN;
170 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 171 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
171 if (presence != null) 172 if (presence != null)
172 { 173 {
@@ -226,9 +227,9 @@ namespace OpenSim.Region.Framework.Scenes
226 return 0.0; 227 return 0.0;
227 228
228 // Use group position for child prims 229 // Use group position for child prims
229 Vector3 entityPos = entity.AbsolutePosition; 230 Vector3 entityPos;
230 if (entity is SceneObjectPart) 231 if (entity is SceneObjectPart)
231 entityPos = m_scene.GetGroupByPrim(entity.LocalId).AbsolutePosition; 232 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
232 else 233 else
233 entityPos = entity.AbsolutePosition; 234 entityPos = entity.AbsolutePosition;
234 235
@@ -251,12 +252,19 @@ namespace OpenSim.Region.Framework.Scenes
251 252
252 if (entity is SceneObjectPart) 253 if (entity is SceneObjectPart)
253 { 254 {
254 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
255 if (physActor == null || !physActor.IsPhysical)
256 priority += 100;
257
258 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) 255 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
256 {
259 priority = 1.0; 257 priority = 1.0;
258 }
259 else
260 {
261 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
262 if (physActor == null || !physActor.IsPhysical)
263 priority += 100;
264 }
265
266 if (((SceneObjectPart)entity).ParentGroup.RootPart != (SceneObjectPart)entity)
267 priority +=1;
260 } 268 }
261 return priority; 269 return priority;
262 } 270 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 2cf0ced..52e2e83 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -99,34 +99,22 @@ namespace OpenSim.Region.Framework.Scenes
99 /// <param name="item"></param> 99 /// <param name="item"></param>
100 public bool AddInventoryItem(InventoryItemBase item) 100 public bool AddInventoryItem(InventoryItemBase item)
101 { 101 {
102 if (UUID.Zero == item.Folder) 102 InventoryFolderBase folder;
103
104 if (item.Folder == UUID.Zero)
103 { 105 {
104 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 106 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
105 if (f != null) 107 if (folder == null)
106 {
107// m_log.DebugFormat(
108// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}",
109// f.Name, (AssetType)f.Type, item.Name);
110
111 item.Folder = f.ID;
112 }
113 else
114 { 108 {
115 f = InventoryService.GetRootFolder(item.Owner); 109 folder = InventoryService.GetRootFolder(item.Owner);
116 if (f != null) 110
117 { 111 if (folder == null)
118 item.Folder = f.ID;
119 }
120 else
121 {
122 m_log.WarnFormat(
123 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
124 item.Owner, item.Name);
125 return false; 112 return false;
126 }
127 } 113 }
114
115 item.Folder = folder.ID;
128 } 116 }
129 117
130 if (InventoryService.AddItem(item)) 118 if (InventoryService.AddItem(item))
131 { 119 {
132 int userlevel = 0; 120 int userlevel = 0;
@@ -252,8 +240,7 @@ namespace OpenSim.Region.Framework.Scenes
252 240
253 // Update item with new asset 241 // Update item with new asset
254 item.AssetID = asset.FullID; 242 item.AssetID = asset.FullID;
255 if (group.UpdateInventoryItem(item)) 243 group.UpdateInventoryItem(item);
256 remoteClient.SendAgentAlertMessage("Script saved", false);
257 244
258 part.GetProperties(remoteClient); 245 part.GetProperties(remoteClient);
259 246
@@ -264,12 +251,7 @@ namespace OpenSim.Region.Framework.Scenes
264 { 251 {
265 // Needs to determine which engine was running it and use that 252 // Needs to determine which engine was running it and use that
266 // 253 //
267 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 254 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
268 errors = part.Inventory.GetScriptErrors(item.ItemID);
269 }
270 else
271 {
272 remoteClient.SendAgentAlertMessage("Script saved", false);
273 } 255 }
274 part.ParentGroup.ResumeScripts(); 256 part.ParentGroup.ResumeScripts();
275 return errors; 257 return errors;
@@ -688,6 +670,8 @@ namespace OpenSim.Region.Framework.Scenes
688 return; 670 return;
689 } 671 }
690 672
673 if (newName == null) newName = item.Name;
674
691 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 675 AssetBase asset = AssetService.Get(item.AssetID.ToString());
692 676
693 if (asset != null) 677 if (asset != null)
@@ -735,6 +719,24 @@ namespace OpenSim.Region.Framework.Scenes
735 } 719 }
736 720
737 /// <summary> 721 /// <summary>
722 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
723 /// </summary>
724 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
725 {
726 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
727 foreach (InventoryItemBase b in items)
728 {
729 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
730 InventoryItemBase n = InventoryService.GetItem(b);
731 n.Folder = destfolder;
732 moveitems.Add(n);
733 remoteClient.SendInventoryItemCreateUpdate(n, 0);
734 }
735
736 MoveInventoryItem(remoteClient, moveitems);
737 }
738
739 /// <summary>
738 /// Move an item within the agent's inventory. 740 /// Move an item within the agent's inventory.
739 /// </summary> 741 /// </summary>
740 /// <param name="remoteClient"></param> 742 /// <param name="remoteClient"></param>
@@ -978,8 +980,12 @@ namespace OpenSim.Region.Framework.Scenes
978 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 980 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
979 { 981 {
980 SceneObjectPart part = GetSceneObjectPart(localID); 982 SceneObjectPart part = GetSceneObjectPart(localID);
981 SceneObjectGroup group = part.ParentGroup; 983 SceneObjectGroup group = null;
982 if (group != null) 984 if (part != null)
985 {
986 group = part.ParentGroup;
987 }
988 if (part != null && group != null)
983 { 989 {
984 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 990 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
985 return; 991 return;
@@ -1428,13 +1434,6 @@ namespace OpenSim.Region.Framework.Scenes
1428 { 1434 {
1429 agentTransactions.HandleTaskItemUpdateFromTransaction( 1435 agentTransactions.HandleTaskItemUpdateFromTransaction(
1430 remoteClient, part, transactionID, currentItem); 1436 remoteClient, part, transactionID, currentItem);
1431
1432 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1433 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1434 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1435 remoteClient.SendAgentAlertMessage("Script saved", false);
1436 else
1437 remoteClient.SendAgentAlertMessage("Item saved", false);
1438 } 1437 }
1439 1438
1440 // Base ALWAYS has move 1439 // Base ALWAYS has move
@@ -1552,7 +1551,7 @@ namespace OpenSim.Region.Framework.Scenes
1552 return; 1551 return;
1553 1552
1554 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1553 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1555 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1554 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1556 remoteClient.AgentId); 1555 remoteClient.AgentId);
1557 AssetService.Store(asset); 1556 AssetService.Store(asset);
1558 1557
@@ -1705,23 +1704,32 @@ namespace OpenSim.Region.Framework.Scenes
1705 // build a list of eligible objects 1704 // build a list of eligible objects
1706 List<uint> deleteIDs = new List<uint>(); 1705 List<uint> deleteIDs = new List<uint>();
1707 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1706 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1708 1707 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1709 // Start with true for both, then remove the flags if objects
1710 // that we can't derez are part of the selection
1711 bool permissionToTake = true;
1712 bool permissionToTakeCopy = true;
1713 bool permissionToDelete = true;
1714 1708
1715 foreach (uint localID in localIDs) 1709 foreach (uint localID in localIDs)
1716 { 1710 {
1711 // Start with true for both, then remove the flags if objects
1712 // that we can't derez are part of the selection
1713 bool permissionToTake = true;
1714 bool permissionToTakeCopy = true;
1715 bool permissionToDelete = true;
1716
1717 // Invalid id 1717 // Invalid id
1718 SceneObjectPart part = GetSceneObjectPart(localID); 1718 SceneObjectPart part = GetSceneObjectPart(localID);
1719 if (part == null) 1719 if (part == null)
1720 {
1721 //Client still thinks the object exists, kill it
1722 deleteIDs.Add(localID);
1720 continue; 1723 continue;
1724 }
1721 1725
1722 // Already deleted by someone else 1726 // Already deleted by someone else
1723 if (part.ParentGroup == null || part.ParentGroup.IsDeleted) 1727 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
1728 {
1729 //Client still thinks the object exists, kill it
1730 deleteIDs.Add(localID);
1724 continue; 1731 continue;
1732 }
1725 1733
1726 // Can't delete child prims 1734 // Can't delete child prims
1727 if (part != part.ParentGroup.RootPart) 1735 if (part != part.ParentGroup.RootPart)
@@ -1729,9 +1737,6 @@ namespace OpenSim.Region.Framework.Scenes
1729 1737
1730 SceneObjectGroup grp = part.ParentGroup; 1738 SceneObjectGroup grp = part.ParentGroup;
1731 1739
1732 deleteIDs.Add(localID);
1733 deleteGroups.Add(grp);
1734
1735 if (remoteClient == null) 1740 if (remoteClient == null)
1736 { 1741 {
1737 // Autoreturn has a null client. Nothing else does. So 1742 // Autoreturn has a null client. Nothing else does. So
@@ -1748,80 +1753,104 @@ namespace OpenSim.Region.Framework.Scenes
1748 } 1753 }
1749 else 1754 else
1750 { 1755 {
1751 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1756 if (action == DeRezAction.TakeCopy)
1757 {
1758 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1759 permissionToTakeCopy = false;
1760 }
1761 else
1762 {
1752 permissionToTakeCopy = false; 1763 permissionToTakeCopy = false;
1753 1764 }
1754 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1765 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1755 permissionToTake = false; 1766 permissionToTake = false;
1756 1767
1757 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1768 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1758 permissionToDelete = false; 1769 permissionToDelete = false;
1759 } 1770 }
1760 }
1761 1771
1762 // Handle god perms 1772 // Handle god perms
1763 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1773 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1764 { 1774 {
1765 permissionToTake = true; 1775 permissionToTake = true;
1766 permissionToTakeCopy = true; 1776 permissionToTakeCopy = true;
1767 permissionToDelete = true; 1777 permissionToDelete = true;
1768 } 1778 }
1769 1779
1770 // If we're re-saving, we don't even want to delete 1780 // If we're re-saving, we don't even want to delete
1771 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1781 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1772 permissionToDelete = false; 1782 permissionToDelete = false;
1773 1783
1774 // if we want to take a copy, we also don't want to delete 1784 // if we want to take a copy, we also don't want to delete
1775 // Note: after this point, the permissionToTakeCopy flag 1785 // Note: after this point, the permissionToTakeCopy flag
1776 // becomes irrelevant. It already includes the permissionToTake 1786 // becomes irrelevant. It already includes the permissionToTake
1777 // permission and after excluding no copy items here, we can 1787 // permission and after excluding no copy items here, we can
1778 // just use that. 1788 // just use that.
1779 if (action == DeRezAction.TakeCopy) 1789 if (action == DeRezAction.TakeCopy)
1780 { 1790 {
1781 // If we don't have permission, stop right here 1791 // If we don't have permission, stop right here
1782 if (!permissionToTakeCopy) 1792 if (!permissionToTakeCopy)
1783 return; 1793 return;
1784 1794
1785 permissionToTake = true; 1795 permissionToTake = true;
1786 // Don't delete 1796 // Don't delete
1787 permissionToDelete = false; 1797 permissionToDelete = false;
1788 } 1798 }
1789 1799
1790 if (action == DeRezAction.Return) 1800 if (action == DeRezAction.Return)
1791 {
1792 if (remoteClient != null)
1793 { 1801 {
1794 if (Permissions.CanReturnObjects( 1802 if (remoteClient != null)
1795 null,
1796 remoteClient.AgentId,
1797 deleteGroups))
1798 { 1803 {
1799 permissionToTake = true; 1804 if (Permissions.CanReturnObjects(
1800 permissionToDelete = true; 1805 null,
1801 1806 remoteClient.AgentId,
1802 foreach (SceneObjectGroup g in deleteGroups) 1807 deleteGroups))
1803 { 1808 {
1804 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1809 permissionToTake = true;
1810 permissionToDelete = true;
1811
1812 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1805 } 1813 }
1806 } 1814 }
1815 else // Auto return passes through here with null agent
1816 {
1817 permissionToTake = true;
1818 permissionToDelete = true;
1819 }
1807 } 1820 }
1808 else // Auto return passes through here with null agent 1821
1822 if (permissionToTake && (!permissionToDelete))
1823 takeGroups.Add(grp);
1824
1825 if (permissionToDelete)
1809 { 1826 {
1810 permissionToTake = true; 1827 if (permissionToTake)
1811 permissionToDelete = true; 1828 deleteGroups.Add(grp);
1829 deleteIDs.Add(grp.LocalId);
1812 } 1830 }
1813 } 1831 }
1814 1832
1815 if (permissionToTake) 1833 SendKillObject(deleteIDs);
1834
1835 if (deleteGroups.Count > 0)
1816 { 1836 {
1837 foreach (SceneObjectGroup g in deleteGroups)
1838 deleteIDs.Remove(g.LocalId);
1839
1817 m_asyncSceneObjectDeleter.DeleteToInventory( 1840 m_asyncSceneObjectDeleter.DeleteToInventory(
1818 action, destinationID, deleteGroups, remoteClient, 1841 action, destinationID, deleteGroups, remoteClient,
1819 permissionToDelete); 1842 true);
1843 }
1844 if (takeGroups.Count > 0)
1845 {
1846 m_asyncSceneObjectDeleter.DeleteToInventory(
1847 action, destinationID, takeGroups, remoteClient,
1848 false);
1820 } 1849 }
1821 else if (permissionToDelete) 1850 if (deleteIDs.Count > 0)
1822 { 1851 {
1823 foreach (SceneObjectGroup g in deleteGroups) 1852 foreach (SceneObjectGroup g in deleteGroups)
1824 DeleteSceneObject(g, false); 1853 DeleteSceneObject(g, true);
1825 } 1854 }
1826 } 1855 }
1827 1856
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 66c6924..792115a 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -84,6 +84,7 @@ namespace OpenSim.Region.Framework.Scenes
84 // TODO: need to figure out how allow client agents but deny 84 // TODO: need to figure out how allow client agents but deny
85 // root agents when ACL denies access to root agent 85 // root agents when ACL denies access to root agent
86 public bool m_strictAccessControl = true; 86 public bool m_strictAccessControl = true;
87 public bool m_seeIntoBannedRegion = false;
87 public int MaxUndoCount = 5; 88 public int MaxUndoCount = 5;
88 public bool LoginsDisabled = true; 89 public bool LoginsDisabled = true;
89 public bool LoadingPrims; 90 public bool LoadingPrims;
@@ -102,6 +103,7 @@ namespace OpenSim.Region.Framework.Scenes
102 protected ModuleLoader m_moduleLoader; 103 protected ModuleLoader m_moduleLoader;
103 protected AgentCircuitManager m_authenticateHandler; 104 protected AgentCircuitManager m_authenticateHandler;
104 protected SceneCommunicationService m_sceneGridService; 105 protected SceneCommunicationService m_sceneGridService;
106 protected ISnmpModule m_snmpService = null;
105 107
106 protected ISimulationDataService m_SimulationDataService; 108 protected ISimulationDataService m_SimulationDataService;
107 protected IEstateDataService m_EstateDataService; 109 protected IEstateDataService m_EstateDataService;
@@ -163,6 +165,7 @@ namespace OpenSim.Region.Framework.Scenes
163 private int landMS; 165 private int landMS;
164 private int lastCompletedFrame; 166 private int lastCompletedFrame;
165 167
168 public bool CombineRegions = false;
166 private bool m_physics_enabled = true; 169 private bool m_physics_enabled = true;
167 private bool m_scripts_enabled = true; 170 private bool m_scripts_enabled = true;
168 private string m_defaultScriptEngine; 171 private string m_defaultScriptEngine;
@@ -171,6 +174,8 @@ namespace OpenSim.Region.Framework.Scenes
171 private volatile bool shuttingdown; 174 private volatile bool shuttingdown;
172 175
173 private int m_lastUpdate; 176 private int m_lastUpdate;
177 private int m_lastIncoming;
178 private int m_lastOutgoing;
174 private bool m_firstHeartbeat = true; 179 private bool m_firstHeartbeat = true;
175 180
176 private object m_deleting_scene_object = new object(); 181 private object m_deleting_scene_object = new object();
@@ -220,6 +225,19 @@ namespace OpenSim.Region.Framework.Scenes
220 get { return m_sceneGridService; } 225 get { return m_sceneGridService; }
221 } 226 }
222 227
228 public ISnmpModule SnmpService
229 {
230 get
231 {
232 if (m_snmpService == null)
233 {
234 m_snmpService = RequestModuleInterface<ISnmpModule>();
235 }
236
237 return m_snmpService;
238 }
239 }
240
223 public ISimulationDataService SimulationDataService 241 public ISimulationDataService SimulationDataService
224 { 242 {
225 get 243 get
@@ -551,6 +569,8 @@ namespace OpenSim.Region.Framework.Scenes
551 m_regionName = m_regInfo.RegionName; 569 m_regionName = m_regInfo.RegionName;
552 m_datastore = m_regInfo.DataStore; 570 m_datastore = m_regInfo.DataStore;
553 m_lastUpdate = Util.EnvironmentTickCount(); 571 m_lastUpdate = Util.EnvironmentTickCount();
572 m_lastIncoming = 0;
573 m_lastOutgoing = 0;
554 574
555 m_physicalPrim = physicalPrim; 575 m_physicalPrim = physicalPrim;
556 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor; 576 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
@@ -564,6 +584,8 @@ namespace OpenSim.Region.Framework.Scenes
564 #region Region Settings 584 #region Region Settings
565 585
566 // Load region settings 586 // Load region settings
587 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID);
588
567 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID); 589 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
568 if (estateDataService != null) 590 if (estateDataService != null)
569 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 591 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -623,9 +645,10 @@ namespace OpenSim.Region.Framework.Scenes
623 //Animation states 645 //Animation states
624 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 646 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
625 // TODO: Change default to true once the feature is supported 647 // TODO: Change default to true once the feature is supported
626 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 648 m_usePreJump = startupConfig.GetBoolean("enableprejump", true);
627
628 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 649 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
650
651 m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF");
629 if (RegionInfo.NonphysPrimMax > 0) 652 if (RegionInfo.NonphysPrimMax > 0)
630 { 653 {
631 m_maxNonphys = RegionInfo.NonphysPrimMax; 654 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -657,6 +680,7 @@ namespace OpenSim.Region.Framework.Scenes
657 m_persistAfter *= 10000000; 680 m_persistAfter *= 10000000;
658 681
659 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 682 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
683 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
660 684
661 IConfig packetConfig = m_config.Configs["PacketPool"]; 685 IConfig packetConfig = m_config.Configs["PacketPool"];
662 if (packetConfig != null) 686 if (packetConfig != null)
@@ -666,6 +690,8 @@ namespace OpenSim.Region.Framework.Scenes
666 } 690 }
667 691
668 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 692 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
693 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
694 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
669 695
670 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 696 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
671 if (m_generateMaptiles) 697 if (m_generateMaptiles)
@@ -690,9 +716,9 @@ namespace OpenSim.Region.Framework.Scenes
690 } 716 }
691 } 717 }
692 } 718 }
693 catch 719 catch (Exception e)
694 { 720 {
695 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 721 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
696 } 722 }
697 723
698 #endregion Region Config 724 #endregion Region Config
@@ -1063,6 +1089,7 @@ namespace OpenSim.Region.Framework.Scenes
1063 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1089 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1064 if (HeartbeatThread != null) 1090 if (HeartbeatThread != null)
1065 { 1091 {
1092 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1066 HeartbeatThread.Abort(); 1093 HeartbeatThread.Abort();
1067 HeartbeatThread = null; 1094 HeartbeatThread = null;
1068 } 1095 }
@@ -1186,9 +1213,6 @@ namespace OpenSim.Region.Framework.Scenes
1186 try 1213 try
1187 { 1214 {
1188 Update(); 1215 Update();
1189
1190 m_lastUpdate = Util.EnvironmentTickCount();
1191 m_firstHeartbeat = false;
1192 } 1216 }
1193 catch (ThreadAbortException) 1217 catch (ThreadAbortException)
1194 { 1218 {
@@ -1378,6 +1402,9 @@ namespace OpenSim.Region.Framework.Scenes
1378 1402
1379 // Tell the watchdog that this thread is still alive 1403 // Tell the watchdog that this thread is still alive
1380 Watchdog.UpdateThread(); 1404 Watchdog.UpdateThread();
1405
1406 m_lastUpdate = Util.EnvironmentTickCount();
1407 m_firstHeartbeat = false;
1381 } 1408 }
1382 } 1409 }
1383 1410
@@ -1734,14 +1761,24 @@ namespace OpenSim.Region.Framework.Scenes
1734 /// <returns></returns> 1761 /// <returns></returns>
1735 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1762 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1736 { 1763 {
1764
1765 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1766 Vector3 wpos = Vector3.Zero;
1767 // Check for water surface intersection from above
1768 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1769 {
1770 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1771 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1772 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1773 wpos.Z = wheight;
1774 }
1775
1737 Vector3 pos = Vector3.Zero; 1776 Vector3 pos = Vector3.Zero;
1738 if (RayEndIsIntersection == (byte)1) 1777 if (RayEndIsIntersection == (byte)1)
1739 { 1778 {
1740 pos = RayEnd; 1779 pos = RayEnd;
1741 return pos;
1742 } 1780 }
1743 1781 else if (RayTargetID != UUID.Zero)
1744 if (RayTargetID != UUID.Zero)
1745 { 1782 {
1746 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1783 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1747 1784
@@ -1763,7 +1800,7 @@ namespace OpenSim.Region.Framework.Scenes
1763 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1800 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1764 1801
1765 // Un-comment out the following line to Get Raytrace results printed to the console. 1802 // Un-comment out the following line to Get Raytrace results printed to the console.
1766 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1803 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1767 float ScaleOffset = 0.5f; 1804 float ScaleOffset = 0.5f;
1768 1805
1769 // If we hit something 1806 // If we hit something
@@ -1786,13 +1823,10 @@ namespace OpenSim.Region.Framework.Scenes
1786 //pos.Z -= 0.25F; 1823 //pos.Z -= 0.25F;
1787 1824
1788 } 1825 }
1789
1790 return pos;
1791 } 1826 }
1792 else 1827 else
1793 { 1828 {
1794 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1829 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1795
1796 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1830 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1797 1831
1798 // Un-comment the following line to print the raytrace results to the console. 1832 // Un-comment the following line to print the raytrace results to the console.
@@ -1801,13 +1835,12 @@ namespace OpenSim.Region.Framework.Scenes
1801 if (ei.HitTF) 1835 if (ei.HitTF)
1802 { 1836 {
1803 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1837 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1804 } else 1838 }
1839 else
1805 { 1840 {
1806 // fall back to our stupid functionality 1841 // fall back to our stupid functionality
1807 pos = RayEnd; 1842 pos = RayEnd;
1808 } 1843 }
1809
1810 return pos;
1811 } 1844 }
1812 } 1845 }
1813 else 1846 else
@@ -1818,8 +1851,12 @@ namespace OpenSim.Region.Framework.Scenes
1818 //increase height so its above the ground. 1851 //increase height so its above the ground.
1819 //should be getting the normal of the ground at the rez point and using that? 1852 //should be getting the normal of the ground at the rez point and using that?
1820 pos.Z += scale.Z / 2f; 1853 pos.Z += scale.Z / 2f;
1821 return pos; 1854// return pos;
1822 } 1855 }
1856
1857 // check against posible water intercept
1858 if (wpos.Z > pos.Z) pos = wpos;
1859 return pos;
1823 } 1860 }
1824 1861
1825 1862
@@ -1899,7 +1936,10 @@ namespace OpenSim.Region.Framework.Scenes
1899 public bool AddRestoredSceneObject( 1936 public bool AddRestoredSceneObject(
1900 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1937 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1901 { 1938 {
1902 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1939 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1940 if (result)
1941 sceneObject.IsDeleted = false;
1942 return result;
1903 } 1943 }
1904 1944
1905 /// <summary> 1945 /// <summary>
@@ -1976,6 +2016,15 @@ namespace OpenSim.Region.Framework.Scenes
1976 /// </summary> 2016 /// </summary>
1977 public void DeleteAllSceneObjects() 2017 public void DeleteAllSceneObjects()
1978 { 2018 {
2019 DeleteAllSceneObjects(false);
2020 }
2021
2022 /// <summary>
2023 /// Delete every object from the scene. This does not include attachments worn by avatars.
2024 /// </summary>
2025 public void DeleteAllSceneObjects(bool exceptNoCopy)
2026 {
2027 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1979 lock (Entities) 2028 lock (Entities)
1980 { 2029 {
1981 EntityBase[] entities = Entities.GetEntities(); 2030 EntityBase[] entities = Entities.GetEntities();
@@ -1984,11 +2033,24 @@ namespace OpenSim.Region.Framework.Scenes
1984 if (e is SceneObjectGroup) 2033 if (e is SceneObjectGroup)
1985 { 2034 {
1986 SceneObjectGroup sog = (SceneObjectGroup)e; 2035 SceneObjectGroup sog = (SceneObjectGroup)e;
1987 if (!sog.IsAttachment) 2036 if (sog != null && !sog.IsAttachment)
1988 DeleteSceneObject((SceneObjectGroup)e, false); 2037 {
2038 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2039 {
2040 DeleteSceneObject((SceneObjectGroup)e, false);
2041 }
2042 else
2043 {
2044 toReturn.Add((SceneObjectGroup)e);
2045 }
2046 }
1989 } 2047 }
1990 } 2048 }
1991 } 2049 }
2050 if (toReturn.Count > 0)
2051 {
2052 returnObjects(toReturn.ToArray(), UUID.Zero);
2053 }
1992 } 2054 }
1993 2055
1994 /// <summary> 2056 /// <summary>
@@ -2037,6 +2099,8 @@ namespace OpenSim.Region.Framework.Scenes
2037 } 2099 }
2038 2100
2039 group.DeleteGroupFromScene(silent); 2101 group.DeleteGroupFromScene(silent);
2102 if (!silent)
2103 SendKillObject(new List<uint>() { group.LocalId });
2040 2104
2041// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2105// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2042 } 2106 }
@@ -2367,6 +2431,12 @@ namespace OpenSim.Region.Framework.Scenes
2367 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2431 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2368 public bool AddSceneObject(SceneObjectGroup sceneObject) 2432 public bool AddSceneObject(SceneObjectGroup sceneObject)
2369 { 2433 {
2434 if (sceneObject.OwnerID == UUID.Zero)
2435 {
2436 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2437 return false;
2438 }
2439
2370 // If the user is banned, we won't let any of their objects 2440 // If the user is banned, we won't let any of their objects
2371 // enter. Period. 2441 // enter. Period.
2372 // 2442 //
@@ -2414,15 +2484,28 @@ namespace OpenSim.Region.Framework.Scenes
2414 2484
2415 if (AttachmentsModule != null) 2485 if (AttachmentsModule != null)
2416 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2486 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2487
2488 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2417 } 2489 }
2418 else 2490 else
2419 { 2491 {
2492 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2420 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2493 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2421 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2494 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2422 } 2495 }
2496 if (sceneObject.OwnerID == UUID.Zero)
2497 {
2498 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2499 return false;
2500 }
2423 } 2501 }
2424 else 2502 else
2425 { 2503 {
2504 if (sceneObject.OwnerID == UUID.Zero)
2505 {
2506 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2507 return false;
2508 }
2426 AddRestoredSceneObject(sceneObject, true, false); 2509 AddRestoredSceneObject(sceneObject, true, false);
2427 2510
2428 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2511 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2534,12 +2617,19 @@ namespace OpenSim.Region.Framework.Scenes
2534 } 2617 }
2535 } 2618 }
2536 2619
2537 if (GetScenePresence(client.AgentId) != null) 2620 if (TryGetScenePresence(client.AgentId, out presence))
2538 { 2621 {
2539 m_LastLogin = Util.EnvironmentTickCount(); 2622 m_LastLogin = Util.EnvironmentTickCount();
2540 EventManager.TriggerOnNewClient(client); 2623 EventManager.TriggerOnNewClient(client);
2541 if (vialogin) 2624 if (vialogin)
2625 {
2542 EventManager.TriggerOnClientLogin(client); 2626 EventManager.TriggerOnClientLogin(client);
2627
2628 // Send initial parcel data
2629 Vector3 pos = presence.AbsolutePosition;
2630 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2631 land.SendLandUpdateToClient(presence.ControllingClient);
2632 }
2543 } 2633 }
2544 } 2634 }
2545 2635
@@ -2695,6 +2785,7 @@ namespace OpenSim.Region.Framework.Scenes
2695 client.OnFetchInventory += HandleFetchInventory; 2785 client.OnFetchInventory += HandleFetchInventory;
2696 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2786 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2697 client.OnCopyInventoryItem += CopyInventoryItem; 2787 client.OnCopyInventoryItem += CopyInventoryItem;
2788 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2698 client.OnMoveInventoryItem += MoveInventoryItem; 2789 client.OnMoveInventoryItem += MoveInventoryItem;
2699 client.OnRemoveInventoryItem += RemoveInventoryItem; 2790 client.OnRemoveInventoryItem += RemoveInventoryItem;
2700 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2791 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2873,15 +2964,16 @@ namespace OpenSim.Region.Framework.Scenes
2873 /// </summary> 2964 /// </summary>
2874 /// <param name="agentId">The avatar's Unique ID</param> 2965 /// <param name="agentId">The avatar's Unique ID</param>
2875 /// <param name="client">The IClientAPI for the client</param> 2966 /// <param name="client">The IClientAPI for the client</param>
2876 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 2967 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2877 { 2968 {
2878 if (m_teleportModule != null) 2969 if (m_teleportModule != null)
2879 m_teleportModule.TeleportHome(agentId, client); 2970 return m_teleportModule.TeleportHome(agentId, client);
2880 else 2971 else
2881 { 2972 {
2882 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 2973 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2883 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 2974 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2884 } 2975 }
2976 return false;
2885 } 2977 }
2886 2978
2887 /// <summary> 2979 /// <summary>
@@ -2980,6 +3072,16 @@ namespace OpenSim.Region.Framework.Scenes
2980 /// <param name="flags"></param> 3072 /// <param name="flags"></param>
2981 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3073 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
2982 { 3074 {
3075 //Add half the avatar's height so that the user doesn't fall through prims
3076 ScenePresence presence;
3077 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3078 {
3079 if (presence.Appearance != null)
3080 {
3081 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3082 }
3083 }
3084
2983 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3085 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
2984 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3086 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
2985 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3087 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3073,7 +3175,9 @@ namespace OpenSim.Region.Framework.Scenes
3073 regions.Remove(RegionInfo.RegionHandle); 3175 regions.Remove(RegionInfo.RegionHandle);
3074 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3176 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3075 } 3177 }
3178 m_log.Debug("[Scene] Beginning ClientClosed");
3076 m_eventManager.TriggerClientClosed(agentID, this); 3179 m_eventManager.TriggerClientClosed(agentID, this);
3180 m_log.Debug("[Scene] Finished ClientClosed");
3077 } 3181 }
3078 catch (NullReferenceException) 3182 catch (NullReferenceException)
3079 { 3183 {
@@ -3081,7 +3185,12 @@ namespace OpenSim.Region.Framework.Scenes
3081 // Avatar is already disposed :/ 3185 // Avatar is already disposed :/
3082 } 3186 }
3083 3187
3188 m_log.Debug("[Scene] Beginning OnRemovePresence");
3084 m_eventManager.TriggerOnRemovePresence(agentID); 3189 m_eventManager.TriggerOnRemovePresence(agentID);
3190 m_log.Debug("[Scene] Finished OnRemovePresence");
3191
3192 if (avatar != null && (!avatar.IsChildAgent))
3193 avatar.SaveChangedAttachments();
3085 3194
3086 if (avatar != null && (!avatar.IsChildAgent)) 3195 if (avatar != null && (!avatar.IsChildAgent))
3087 avatar.SaveChangedAttachments(); 3196 avatar.SaveChangedAttachments();
@@ -3090,7 +3199,7 @@ namespace OpenSim.Region.Framework.Scenes
3090 delegate(IClientAPI client) 3199 delegate(IClientAPI client)
3091 { 3200 {
3092 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3201 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3093 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3202 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3094 catch (NullReferenceException) { } 3203 catch (NullReferenceException) { }
3095 }); 3204 });
3096 3205
@@ -3101,8 +3210,11 @@ namespace OpenSim.Region.Framework.Scenes
3101 } 3210 }
3102 3211
3103 // Remove the avatar from the scene 3212 // Remove the avatar from the scene
3213 m_log.Debug("[Scene] Begin RemoveScenePresence");
3104 m_sceneGraph.RemoveScenePresence(agentID); 3214 m_sceneGraph.RemoveScenePresence(agentID);
3215 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3105 m_clientManager.Remove(agentID); 3216 m_clientManager.Remove(agentID);
3217 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3106 3218
3107 try 3219 try
3108 { 3220 {
@@ -3116,9 +3228,10 @@ namespace OpenSim.Region.Framework.Scenes
3116 { 3228 {
3117 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3229 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3118 } 3230 }
3119 3231 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3120 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3232 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3121 CleanDroppedAttachments(); 3233 CleanDroppedAttachments();
3234 m_log.Debug("[Scene] The avatar has left the building");
3122 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3235 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3123 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3236 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3124 } 3237 }
@@ -3149,18 +3262,24 @@ namespace OpenSim.Region.Framework.Scenes
3149 3262
3150 #region Entities 3263 #region Entities
3151 3264
3152 public void SendKillObject(uint localID) 3265 public void SendKillObject(List<uint> localIDs)
3153 { 3266 {
3154 SceneObjectPart part = GetSceneObjectPart(localID); 3267 List<uint> deleteIDs = new List<uint>();
3155 if (part != null) // It is a prim 3268
3269 foreach (uint localID in localIDs)
3156 { 3270 {
3157 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3271 SceneObjectPart part = GetSceneObjectPart(localID);
3272 if (part != null) // It is a prim
3158 { 3273 {
3159 if (part.ParentGroup.RootPart != part) // Child part 3274 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3160 return; 3275 {
3276 if (part.ParentGroup.RootPart != part) // Child part
3277 continue;
3278 }
3161 } 3279 }
3280 deleteIDs.Add(localID);
3162 } 3281 }
3163 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); 3282 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3164 } 3283 }
3165 3284
3166 #endregion 3285 #endregion
@@ -3178,7 +3297,6 @@ namespace OpenSim.Region.Framework.Scenes
3178 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3297 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3179 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3298 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3180 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3299 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3181 m_sceneGridService.KiPrimitive += SendKillObject;
3182 m_sceneGridService.OnGetLandData += GetLandData; 3300 m_sceneGridService.OnGetLandData += GetLandData;
3183 } 3301 }
3184 3302
@@ -3187,7 +3305,6 @@ namespace OpenSim.Region.Framework.Scenes
3187 /// </summary> 3305 /// </summary>
3188 public void UnRegisterRegionWithComms() 3306 public void UnRegisterRegionWithComms()
3189 { 3307 {
3190 m_sceneGridService.KiPrimitive -= SendKillObject;
3191 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3308 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3192 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3309 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3193 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3310 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3274,6 +3391,7 @@ namespace OpenSim.Region.Framework.Scenes
3274 { 3391 {
3275 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3392 if (land != null && !TestLandRestrictions(agent, land, out reason))
3276 { 3393 {
3394 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3277 return false; 3395 return false;
3278 } 3396 }
3279 } 3397 }
@@ -3391,6 +3509,8 @@ namespace OpenSim.Region.Framework.Scenes
3391 } 3509 }
3392 } 3510 }
3393 // Honor parcel landing type and position. 3511 // Honor parcel landing type and position.
3512 /*
3513 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3394 if (land != null) 3514 if (land != null)
3395 { 3515 {
3396 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3516 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3398,6 +3518,7 @@ namespace OpenSim.Region.Framework.Scenes
3398 agent.startpos = land.LandData.UserLocation; 3518 agent.startpos = land.LandData.UserLocation;
3399 } 3519 }
3400 } 3520 }
3521 */// This is now handled properly in ScenePresence.MakeRootAgent
3401 } 3522 }
3402 3523
3403 return true; 3524 return true;
@@ -3493,7 +3614,7 @@ namespace OpenSim.Region.Framework.Scenes
3493 3614
3494 if (m_regInfo.EstateSettings != null) 3615 if (m_regInfo.EstateSettings != null)
3495 { 3616 {
3496 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3617 if ((!m_seeIntoBannedRegion) && m_regInfo.EstateSettings.IsBanned(agent.AgentID))
3497 { 3618 {
3498 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3619 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3499 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3620 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3683,6 +3804,12 @@ namespace OpenSim.Region.Framework.Scenes
3683 3804
3684 // We have to wait until the viewer contacts this region after receiving EAC. 3805 // We have to wait until the viewer contacts this region after receiving EAC.
3685 // That calls AddNewClient, which finally creates the ScenePresence 3806 // That calls AddNewClient, which finally creates the ScenePresence
3807 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID))
3808 {
3809 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3810 return false;
3811 }
3812
3686 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3813 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3687 if (nearestParcel == null) 3814 if (nearestParcel == null)
3688 { 3815 {
@@ -3690,6 +3817,14 @@ namespace OpenSim.Region.Framework.Scenes
3690 return false; 3817 return false;
3691 } 3818 }
3692 3819
3820 int num = m_sceneGraph.GetNumberOfScenePresences();
3821
3822 if (num >= RegionInfo.RegionSettings.AgentLimit)
3823 {
3824 if (!Permissions.IsAdministrator(cAgentData.AgentID))
3825 return false;
3826 }
3827
3693 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3828 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3694 if (childAgentUpdate != null) 3829 if (childAgentUpdate != null)
3695 { 3830 {
@@ -3755,12 +3890,22 @@ namespace OpenSim.Region.Framework.Scenes
3755 return false; 3890 return false;
3756 } 3891 }
3757 3892
3893 public bool IncomingCloseAgent(UUID agentID)
3894 {
3895 return IncomingCloseAgent(agentID, false);
3896 }
3897
3898 public bool IncomingCloseChildAgent(UUID agentID)
3899 {
3900 return IncomingCloseAgent(agentID, true);
3901 }
3902
3758 /// <summary> 3903 /// <summary>
3759 /// Tell a single agent to disconnect from the region. 3904 /// Tell a single agent to disconnect from the region.
3760 /// </summary> 3905 /// </summary>
3761 /// <param name="regionHandle"></param>
3762 /// <param name="agentID"></param> 3906 /// <param name="agentID"></param>
3763 public bool IncomingCloseAgent(UUID agentID) 3907 /// <param name="childOnly"></param>
3908 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3764 { 3909 {
3765 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3910 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3766 3911
@@ -3772,7 +3917,7 @@ namespace OpenSim.Region.Framework.Scenes
3772 { 3917 {
3773 m_sceneGraph.removeUserCount(false); 3918 m_sceneGraph.removeUserCount(false);
3774 } 3919 }
3775 else 3920 else if (!childOnly)
3776 { 3921 {
3777 m_sceneGraph.removeUserCount(true); 3922 m_sceneGraph.removeUserCount(true);
3778 } 3923 }
@@ -3788,9 +3933,12 @@ namespace OpenSim.Region.Framework.Scenes
3788 } 3933 }
3789 else 3934 else
3790 presence.ControllingClient.SendShutdownConnectionNotice(); 3935 presence.ControllingClient.SendShutdownConnectionNotice();
3936 presence.ControllingClient.Close(false);
3937 }
3938 else if (!childOnly)
3939 {
3940 presence.ControllingClient.Close(true);
3791 } 3941 }
3792
3793 presence.ControllingClient.Close();
3794 return true; 3942 return true;
3795 } 3943 }
3796 3944
@@ -4397,34 +4545,66 @@ namespace OpenSim.Region.Framework.Scenes
4397 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4545 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4398 } 4546 }
4399 4547
4400 public int GetHealth() 4548 public int GetHealth(out int flags, out string message)
4401 { 4549 {
4402 // Returns: 4550 // Returns:
4403 // 1 = sim is up and accepting http requests. The heartbeat has 4551 // 1 = sim is up and accepting http requests. The heartbeat has
4404 // stopped and the sim is probably locked up, but a remote 4552 // stopped and the sim is probably locked up, but a remote
4405 // admin restart may succeed 4553 // admin restart may succeed
4406 // 4554 //
4407 // 2 = Sim is up and the heartbeat is running. The sim is likely 4555 // 2 = Sim is up and the heartbeat is running. The sim is likely
4408 // usable for people within and logins _may_ work 4556 // usable for people within
4557 //
4558 // 3 = Sim is up and one packet thread is running. Sim is
4559 // unstable and will not accept new logins
4409 // 4560 //
4410 // 3 = We have seen a new user enter within the past 4 minutes 4561 // 4 = Sim is up and both packet threads are running. Sim is
4562 // likely usable
4563 //
4564 // 5 = We have seen a new user enter within the past 4 minutes
4411 // which can be seen as positive confirmation of sim health 4565 // which can be seen as positive confirmation of sim health
4412 // 4566 //
4567
4568 flags = 0;
4569 message = String.Empty;
4570
4571 CheckHeartbeat();
4572
4573 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4574 {
4575 // We're still starting
4576 // 0 means "in startup", it can't happen another way, since
4577 // to get here, we must be able to accept http connections
4578 return 0;
4579 }
4580
4413 int health=1; // Start at 1, means we're up 4581 int health=1; // Start at 1, means we're up
4414 4582
4415 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4583 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4584 {
4416 health+=1; 4585 health+=1;
4417 else 4586 flags |= 1;
4587 }
4588
4589 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4590 {
4591 health+=1;
4592 flags |= 2;
4593 }
4594
4595 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4596 {
4597 health+=1;
4598 flags |= 4;
4599 }
4600
4601 if (flags != 7)
4418 return health; 4602 return health;
4419 4603
4420 // A login in the last 4 mins? We can't be doing too badly 4604 // A login in the last 4 mins? We can't be doing too badly
4421 // 4605 //
4422 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4606 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4423 health++; 4607 health++;
4424 else
4425 return health;
4426
4427 CheckHeartbeat();
4428 4608
4429 return health; 4609 return health;
4430 } 4610 }
@@ -4875,8 +5055,17 @@ namespace OpenSim.Region.Framework.Scenes
4875 { 5055 {
4876 float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; 5056 float ominX, ominY, ominZ, omaxX, omaxY, omaxZ;
4877 5057
5058 Vector3 vec = g.AbsolutePosition;
5059
4878 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 5060 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
4879 5061
5062 ominX += vec.X;
5063 omaxX += vec.X;
5064 ominY += vec.Y;
5065 omaxY += vec.Y;
5066 ominZ += vec.Z;
5067 omaxZ += vec.Z;
5068
4880 if (minX > ominX) 5069 if (minX > ominX)
4881 minX = ominX; 5070 minX = ominX;
4882 if (minY > ominY) 5071 if (minY > ominY)
@@ -4946,10 +5135,28 @@ namespace OpenSim.Region.Framework.Scenes
4946 }); 5135 });
4947 } 5136 }
4948 5137
4949 foreach (SceneObjectGroup grp in objectsToDelete) 5138 if (objectsToDelete.Count > 0)
5139 {
5140 m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count);
5141 foreach (SceneObjectGroup grp in objectsToDelete)
5142 {
5143 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5144 DeleteSceneObject(grp, true);
5145 }
5146 m_log.Debug("[SCENE]: Finished dropped attachment deletion");
5147 }
5148 }
5149
5150 public void ThreadAlive(int threadCode)
5151 {
5152 switch(threadCode)
4950 { 5153 {
4951 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); 5154 case 1: // Incoming
4952 DeleteSceneObject(grp, true); 5155 m_lastIncoming = Util.EnvironmentTickCount();
5156 break;
5157 case 2: // Incoming
5158 m_lastOutgoing = Util.EnvironmentTickCount();
5159 break;
4953 } 5160 }
4954 } 5161 }
4955 } 5162 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 88e084e..632646d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -44,8 +44,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
44 44
45namespace OpenSim.Region.Framework.Scenes 45namespace OpenSim.Region.Framework.Scenes
46{ 46{
47 public delegate void KiPrimitiveDelegate(uint localID);
48
49 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst); 47 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
50 48
51 /// <summary> 49 /// <summary>
@@ -113,8 +111,6 @@ namespace OpenSim.Region.Framework.Scenes
113// private LogOffUser handlerLogOffUser = null; 111// private LogOffUser handlerLogOffUser = null;
114// private GetLandData handlerGetLandData = null; // OnGetLandData 112// private GetLandData handlerGetLandData = null; // OnGetLandData
115 113
116 public KiPrimitiveDelegate KiPrimitive;
117
118 public SceneCommunicationService() 114 public SceneCommunicationService()
119 { 115 {
120 } 116 }
@@ -168,7 +164,7 @@ namespace OpenSim.Region.Framework.Scenes
168 164
169 if (neighbour != null) 165 if (neighbour != null)
170 { 166 {
171 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 167 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
172 m_scene.EventManager.TriggerOnRegionUp(neighbour); 168 m_scene.EventManager.TriggerOnRegionUp(neighbour);
173 } 169 }
174 else 170 else
@@ -183,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
183 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 179 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
184 180
185 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 181 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
186 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 182 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
187 foreach (GridRegion n in neighbours) 183 foreach (GridRegion n in neighbours)
188 { 184 {
189 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 185 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -267,14 +263,14 @@ namespace OpenSim.Region.Framework.Scenes
267 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle) 263 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
268 { 264 {
269 265
270 m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); 266 //m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
271 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 267 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
272 268
273 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 269 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
274 uint x = 0, y = 0; 270 uint x = 0, y = 0;
275 Utils.LongToUInts(regionHandle, out x, out y); 271 Utils.LongToUInts(regionHandle, out x, out y);
276 GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y); 272 GridRegion destination = m_scene.GridService.GetRegionByPosition(UUID.Zero, (int)x, (int)y);
277 m_scene.SimulationService.CloseAgent(destination, agentID); 273 m_scene.SimulationService.CloseChildAgent(destination, agentID);
278 } 274 }
279 275
280 private void SendCloseChildAgentCompleted(IAsyncResult iar) 276 private void SendCloseChildAgentCompleted(IAsyncResult iar)
@@ -293,7 +289,7 @@ namespace OpenSim.Region.Framework.Scenes
293 d); 289 d);
294 } 290 }
295 } 291 }
296 292
297 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 293 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
298 { 294 {
299 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 295 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 032c859..ecc7f40 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -43,6 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
43 43
44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); 44 public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone);
45 45
46 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
49
50 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
51
46 public delegate void ObjectCreateDelegate(EntityBase obj); 52 public delegate void ObjectCreateDelegate(EntityBase obj);
47 53
48 public delegate void ObjectDeleteDelegate(EntityBase obj); 54 public delegate void ObjectDeleteDelegate(EntityBase obj);
@@ -61,6 +67,9 @@ namespace OpenSim.Region.Framework.Scenes
61 private PhysicsCrash handlerPhysicsCrash = null; 67 private PhysicsCrash handlerPhysicsCrash = null;
62 68
63 public event ObjectDuplicateDelegate OnObjectDuplicate; 69 public event ObjectDuplicateDelegate OnObjectDuplicate;
70 public event AttachToBackupDelegate OnAttachToBackup;
71 public event DetachFromBackupDelegate OnDetachFromBackup;
72 public event ChangedBackupDelegate OnChangeBackup;
64 public event ObjectCreateDelegate OnObjectCreate; 73 public event ObjectCreateDelegate OnObjectCreate;
65 public event ObjectDeleteDelegate OnObjectRemove; 74 public event ObjectDeleteDelegate OnObjectRemove;
66 75
@@ -68,7 +77,7 @@ namespace OpenSim.Region.Framework.Scenes
68 77
69 #region Fields 78 #region Fields
70 79
71 protected object m_presenceLock = new object(); 80 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 81 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 82 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
74 83
@@ -124,13 +133,18 @@ namespace OpenSim.Region.Framework.Scenes
124 133
125 protected internal void Close() 134 protected internal void Close()
126 { 135 {
127 lock (m_presenceLock) 136 m_scenePresencesLock.EnterWriteLock();
137 try
128 { 138 {
129 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 139 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
130 List<ScenePresence> newlist = new List<ScenePresence>(); 140 List<ScenePresence> newlist = new List<ScenePresence>();
131 m_scenePresenceMap = newmap; 141 m_scenePresenceMap = newmap;
132 m_scenePresenceArray = newlist; 142 m_scenePresenceArray = newlist;
133 } 143 }
144 finally
145 {
146 m_scenePresencesLock.ExitWriteLock();
147 }
134 148
135 lock (SceneObjectGroupsByFullID) 149 lock (SceneObjectGroupsByFullID)
136 SceneObjectGroupsByFullID.Clear(); 150 SceneObjectGroupsByFullID.Clear();
@@ -209,27 +223,8 @@ namespace OpenSim.Region.Framework.Scenes
209 if (sp.IsChildAgent) 223 if (sp.IsChildAgent)
210 return; 224 return;
211 225
212 if (sp.ParentID != 0) 226 coarseLocations.Add(sp.AbsolutePosition);
213 { 227 avatarUUIDs.Add(sp.UUID);
214 // sitting avatar
215 SceneObjectPart sop = m_parentScene.GetSceneObjectPart(sp.ParentID);
216 if (sop != null)
217 {
218 coarseLocations.Add(sop.AbsolutePosition + sp.AbsolutePosition);
219 avatarUUIDs.Add(sp.UUID);
220 }
221 else
222 {
223 // we can't find the parent.. ! arg!
224 coarseLocations.Add(sp.AbsolutePosition);
225 avatarUUIDs.Add(sp.UUID);
226 }
227 }
228 else
229 {
230 coarseLocations.Add(sp.AbsolutePosition);
231 avatarUUIDs.Add(sp.UUID);
232 }
233 } 228 }
234 } 229 }
235 230
@@ -259,6 +254,33 @@ namespace OpenSim.Region.Framework.Scenes
259 protected internal bool AddRestoredSceneObject( 254 protected internal bool AddRestoredSceneObject(
260 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 255 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
261 { 256 {
257 if (!m_parentScene.CombineRegions)
258 {
259 // KF: Check for out-of-region, move inside and make static.
260 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
261 sceneObject.RootPart.GroupPosition.Y,
262 sceneObject.RootPart.GroupPosition.Z);
263 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 ||
264 npos.X > Constants.RegionSize ||
265 npos.Y > Constants.RegionSize))
266 {
267 if (npos.X < 0.0) npos.X = 1.0f;
268 if (npos.Y < 0.0) npos.Y = 1.0f;
269 if (npos.Z < 0.0) npos.Z = 0.0f;
270 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
271 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
272
273 foreach (SceneObjectPart part in sceneObject.Parts)
274 {
275 part.GroupPosition = npos;
276 }
277 sceneObject.RootPart.Velocity = Vector3.Zero;
278 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
279 sceneObject.RootPart.Acceleration = Vector3.Zero;
280 sceneObject.RootPart.Velocity = Vector3.Zero;
281 }
282 }
283
262 if (attachToBackup && (!alreadyPersisted)) 284 if (attachToBackup && (!alreadyPersisted))
263 { 285 {
264 sceneObject.ForceInventoryPersistence(); 286 sceneObject.ForceInventoryPersistence();
@@ -458,6 +480,30 @@ namespace OpenSim.Region.Framework.Scenes
458 m_updateList[obj.UUID] = obj; 480 m_updateList[obj.UUID] = obj;
459 } 481 }
460 482
483 public void FireAttachToBackup(SceneObjectGroup obj)
484 {
485 if (OnAttachToBackup != null)
486 {
487 OnAttachToBackup(obj);
488 }
489 }
490
491 public void FireDetachFromBackup(SceneObjectGroup obj)
492 {
493 if (OnDetachFromBackup != null)
494 {
495 OnDetachFromBackup(obj);
496 }
497 }
498
499 public void FireChangeBackup(SceneObjectGroup obj)
500 {
501 if (OnChangeBackup != null)
502 {
503 OnChangeBackup(obj);
504 }
505 }
506
461 /// <summary> 507 /// <summary>
462 /// Process all pending updates 508 /// Process all pending updates
463 /// </summary> 509 /// </summary>
@@ -592,7 +638,8 @@ namespace OpenSim.Region.Framework.Scenes
592 638
593 Entities[presence.UUID] = presence; 639 Entities[presence.UUID] = presence;
594 640
595 lock (m_presenceLock) 641 m_scenePresencesLock.EnterWriteLock();
642 try
596 { 643 {
597 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 644 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
598 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 645 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -616,6 +663,10 @@ namespace OpenSim.Region.Framework.Scenes
616 m_scenePresenceMap = newmap; 663 m_scenePresenceMap = newmap;
617 m_scenePresenceArray = newlist; 664 m_scenePresenceArray = newlist;
618 } 665 }
666 finally
667 {
668 m_scenePresencesLock.ExitWriteLock();
669 }
619 } 670 }
620 671
621 /// <summary> 672 /// <summary>
@@ -630,7 +681,8 @@ namespace OpenSim.Region.Framework.Scenes
630 agentID); 681 agentID);
631 } 682 }
632 683
633 lock (m_presenceLock) 684 m_scenePresencesLock.EnterWriteLock();
685 try
634 { 686 {
635 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 687 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
636 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 688 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -652,6 +704,10 @@ namespace OpenSim.Region.Framework.Scenes
652 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 704 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
653 } 705 }
654 } 706 }
707 finally
708 {
709 m_scenePresencesLock.ExitWriteLock();
710 }
655 } 711 }
656 712
657 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 713 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -775,6 +831,11 @@ namespace OpenSim.Region.Framework.Scenes
775 return m_scenePresenceArray; 831 return m_scenePresenceArray;
776 } 832 }
777 833
834 public int GetNumberOfScenePresences()
835 {
836 return m_scenePresenceArray.Count;
837 }
838
778 /// <summary> 839 /// <summary>
779 /// Request a scene presence by UUID. Fast, indexed lookup. 840 /// Request a scene presence by UUID. Fast, indexed lookup.
780 /// </summary> 841 /// </summary>
@@ -1068,9 +1129,11 @@ namespace OpenSim.Region.Framework.Scenes
1068 /// <param name="action"></param> 1129 /// <param name="action"></param>
1069 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1130 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1070 { 1131 {
1071 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1132 EntityBase[] objlist = Entities.GetAllByType<SceneObjectGroup>();
1072 foreach (SceneObjectGroup obj in objlist) 1133 foreach (EntityBase ent in objlist)
1073 { 1134 {
1135 SceneObjectGroup obj = (SceneObjectGroup)ent;
1136
1074 try 1137 try
1075 { 1138 {
1076 action(obj); 1139 action(obj);
@@ -1531,10 +1594,13 @@ namespace OpenSim.Region.Framework.Scenes
1531 /// <param name="childPrims"></param> 1594 /// <param name="childPrims"></param>
1532 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1595 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1533 { 1596 {
1597 SceneObjectGroup parentGroup = root.ParentGroup;
1598 if (parentGroup == null) return;
1534 Monitor.Enter(m_updateLock); 1599 Monitor.Enter(m_updateLock);
1600
1535 try 1601 try
1536 { 1602 {
1537 SceneObjectGroup parentGroup = root.ParentGroup; 1603 parentGroup.areUpdatesSuspended = true;
1538 1604
1539 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1605 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1540 if (parentGroup != null) 1606 if (parentGroup != null)
@@ -1546,11 +1612,6 @@ namespace OpenSim.Region.Framework.Scenes
1546 1612
1547 if (child != null) 1613 if (child != null)
1548 { 1614 {
1549 // Make sure no child prim is set for sale
1550 // So that, on delink, no prims are unwittingly
1551 // left for sale and sold off
1552 child.RootPart.ObjectSaleType = 0;
1553 child.RootPart.SalePrice = 10;
1554 childGroups.Add(child); 1615 childGroups.Add(child);
1555 } 1616 }
1556 } 1617 }
@@ -1573,12 +1634,13 @@ namespace OpenSim.Region.Framework.Scenes
1573 // occur on link to invoke this elsewhere (such as object selection) 1634 // occur on link to invoke this elsewhere (such as object selection)
1574 parentGroup.RootPart.CreateSelected = true; 1635 parentGroup.RootPart.CreateSelected = true;
1575 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1636 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1576 parentGroup.HasGroupChanged = true;
1577 parentGroup.ScheduleGroupForFullUpdate();
1578
1579 } 1637 }
1580 finally 1638 finally
1581 { 1639 {
1640 parentGroup.areUpdatesSuspended = false;
1641 parentGroup.HasGroupChanged = true;
1642 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1643 parentGroup.ScheduleGroupForFullUpdate();
1582 Monitor.Exit(m_updateLock); 1644 Monitor.Exit(m_updateLock);
1583 } 1645 }
1584 } 1646 }
@@ -1610,21 +1672,24 @@ namespace OpenSim.Region.Framework.Scenes
1610 1672
1611 SceneObjectGroup group = part.ParentGroup; 1673 SceneObjectGroup group = part.ParentGroup;
1612 if (!affectedGroups.Contains(group)) 1674 if (!affectedGroups.Contains(group))
1675 {
1676 group.areUpdatesSuspended = true;
1613 affectedGroups.Add(group); 1677 affectedGroups.Add(group);
1678 }
1614 } 1679 }
1615 } 1680 }
1616 } 1681 }
1617 1682
1618 foreach (SceneObjectPart child in childParts) 1683 if (childParts.Count > 0)
1619 { 1684 {
1620 // Unlink all child parts from their groups 1685 foreach (SceneObjectPart child in childParts)
1621 // 1686 {
1622 child.ParentGroup.DelinkFromGroup(child, true); 1687 // Unlink all child parts from their groups
1623 1688 //
1624 // These are not in affected groups and will not be 1689 child.ParentGroup.DelinkFromGroup(child, true);
1625 // handled further. Do the honors here. 1690 child.ParentGroup.HasGroupChanged = true;
1626 child.ParentGroup.HasGroupChanged = true; 1691 child.ParentGroup.ScheduleGroupForFullUpdate();
1627 child.ParentGroup.ScheduleGroupForFullUpdate(); 1692 }
1628 } 1693 }
1629 1694
1630 foreach (SceneObjectPart root in rootParts) 1695 foreach (SceneObjectPart root in rootParts)
@@ -1634,56 +1699,68 @@ namespace OpenSim.Region.Framework.Scenes
1634 // However, editing linked parts and unlinking may be different 1699 // However, editing linked parts and unlinking may be different
1635 // 1700 //
1636 SceneObjectGroup group = root.ParentGroup; 1701 SceneObjectGroup group = root.ParentGroup;
1702 group.areUpdatesSuspended = true;
1637 1703
1638 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1704 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1639 int numChildren = newSet.Count; 1705 int numChildren = newSet.Count;
1640 1706
1707 if (numChildren == 1)
1708 break;
1709
1641 // If there are prims left in a link set, but the root is 1710 // If there are prims left in a link set, but the root is
1642 // slated for unlink, we need to do this 1711 // slated for unlink, we need to do this
1712 // Unlink the remaining set
1643 // 1713 //
1644 if (numChildren != 1) 1714 bool sendEventsToRemainder = true;
1645 { 1715 if (numChildren > 1)
1646 // Unlink the remaining set 1716 sendEventsToRemainder = false;
1647 //
1648 bool sendEventsToRemainder = true;
1649 if (numChildren > 1)
1650 sendEventsToRemainder = false;
1651 1717
1652 foreach (SceneObjectPart p in newSet) 1718 foreach (SceneObjectPart p in newSet)
1719 {
1720 if (p != group.RootPart)
1653 { 1721 {
1654 if (p != group.RootPart) 1722 group.DelinkFromGroup(p, sendEventsToRemainder);
1655 group.DelinkFromGroup(p, sendEventsToRemainder); 1723 if (numChildren > 2)
1724 {
1725 p.ParentGroup.areUpdatesSuspended = true;
1726 }
1727 else
1728 {
1729 p.ParentGroup.HasGroupChanged = true;
1730 p.ParentGroup.ScheduleGroupForFullUpdate();
1731 }
1656 } 1732 }
1733 }
1734
1735 // If there is more than one prim remaining, we
1736 // need to re-link
1737 //
1738 if (numChildren > 2)
1739 {
1740 // Remove old root
1741 //
1742 if (newSet.Contains(root))
1743 newSet.Remove(root);
1657 1744
1658 // If there is more than one prim remaining, we 1745 // Preserve link ordering
1659 // need to re-link
1660 // 1746 //
1661 if (numChildren > 2) 1747 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1662 { 1748 {
1663 // Remove old root 1749 return a.LinkNum.CompareTo(b.LinkNum);
1664 // 1750 });
1665 if (newSet.Contains(root))
1666 newSet.Remove(root);
1667
1668 // Preserve link ordering
1669 //
1670 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1671 {
1672 return a.LinkNum.CompareTo(b.LinkNum);
1673 });
1674 1751
1675 // Determine new root 1752 // Determine new root
1676 // 1753 //
1677 SceneObjectPart newRoot = newSet[0]; 1754 SceneObjectPart newRoot = newSet[0];
1678 newSet.RemoveAt(0); 1755 newSet.RemoveAt(0);
1679 1756
1680 foreach (SceneObjectPart newChild in newSet) 1757 foreach (SceneObjectPart newChild in newSet)
1681 newChild.UpdateFlag = 0; 1758 newChild.UpdateFlag = 0;
1682 1759
1683 LinkObjects(newRoot, newSet); 1760 newRoot.ParentGroup.areUpdatesSuspended = true;
1684 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1761 LinkObjects(newRoot, newSet);
1685 affectedGroups.Add(newRoot.ParentGroup); 1762 if (!affectedGroups.Contains(newRoot.ParentGroup))
1686 } 1763 affectedGroups.Add(newRoot.ParentGroup);
1687 } 1764 }
1688 } 1765 }
1689 1766
@@ -1691,8 +1768,14 @@ namespace OpenSim.Region.Framework.Scenes
1691 // 1768 //
1692 foreach (SceneObjectGroup g in affectedGroups) 1769 foreach (SceneObjectGroup g in affectedGroups)
1693 { 1770 {
1771 // Child prims that have been unlinked and deleted will
1772 // return unless the root is deleted. This will remove them
1773 // from the database. They will be rewritten immediately,
1774 // minus the rows for the unlinked child prims.
1775 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1694 g.TriggerScriptChangedEvent(Changed.LINK); 1776 g.TriggerScriptChangedEvent(Changed.LINK);
1695 g.HasGroupChanged = true; // Persist 1777 g.HasGroupChanged = true; // Persist
1778 g.areUpdatesSuspended = false;
1696 g.ScheduleGroupForFullUpdate(); 1779 g.ScheduleGroupForFullUpdate();
1697 } 1780 }
1698 } 1781 }
@@ -1807,9 +1890,6 @@ namespace OpenSim.Region.Framework.Scenes
1807 child.ApplyNextOwnerPermissions(); 1890 child.ApplyNextOwnerPermissions();
1808 } 1891 }
1809 } 1892 }
1810
1811 copy.RootPart.ObjectSaleType = 0;
1812 copy.RootPart.SalePrice = 10;
1813 } 1893 }
1814 1894
1815 Entities.Add(copy); 1895 Entities.Add(copy);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index a86223c..6cc7231 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();
@@ -419,6 +415,9 @@ namespace OpenSim.Region.Framework.Scenes
419 415
420 public void ResumeScripts() 416 public void ResumeScripts()
421 { 417 {
418 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
419 return;
420
422 SceneObjectPart[] parts = m_parts.GetArray(); 421 SceneObjectPart[] parts = m_parts.GetArray();
423 for (int i = 0; i < parts.Length; i++) 422 for (int i = 0; i < parts.Length; i++)
424 parts[i].Inventory.ResumeScripts(); 423 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index f17fb28..896300f 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -29,6 +29,7 @@ using 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;
@@ -105,8 +106,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 106 /// since the group's last persistent backup
106 /// </summary> 107 /// </summary>
107 private bool m_hasGroupChanged = false; 108 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 109 private long timeFirstChanged = 0;
109 private long timeLastChanged; 110 private long timeLastChanged = 0;
111 private long m_maxPersistTime = 0;
112 private long m_minPersistTime = 0;
113 private Random m_rand;
114 private bool m_suspendUpdates;
115 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
116
117 public bool areUpdatesSuspended
118 {
119 get
120 {
121 return m_suspendUpdates;
122 }
123 set
124 {
125 m_suspendUpdates = value;
126 if (!value)
127 {
128 QueueForUpdateCheck();
129 }
130 }
131 }
110 132
111 public bool HasGroupChanged 133 public bool HasGroupChanged
112 { 134 {
@@ -114,9 +136,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 136 {
115 if (value) 137 if (value)
116 { 138 {
139 if (m_isBackedUp)
140 {
141 m_scene.SceneGraph.FireChangeBackup(this);
142 }
117 timeLastChanged = DateTime.Now.Ticks; 143 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 144 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 145 timeFirstChanged = DateTime.Now.Ticks;
146 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
147 {
148 if (m_rand == null)
149 {
150 byte[] val = new byte[16];
151 m_rootPart.UUID.ToBytes(val, 0);
152 m_rand = new Random(BitConverter.ToInt32(val, 0));
153 }
154
155 if (m_scene.GetRootAgentCount() == 0)
156 {
157 //If the region is empty, this change has been made by an automated process
158 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
159
160 float factor = 1.5f + (float)(m_rand.NextDouble());
161 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
162 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
163 }
164 else
165 {
166 //If the region is not empty, we want to obey the minimum and maximum persist times
167 //but add a random factor so we stagger the object persistance a little
168 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
169 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
170 }
171 }
120 } 172 }
121 m_hasGroupChanged = value; 173 m_hasGroupChanged = value;
122 174
@@ -141,8 +193,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 193 return false;
142 if (m_scene.ShuttingDown) 194 if (m_scene.ShuttingDown)
143 return true; 195 return true;
196
197 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
198 {
199 m_maxPersistTime = m_scene.m_persistAfter;
200 m_minPersistTime = m_scene.m_dontPersistBefore;
201 }
202
144 long currentTime = DateTime.Now.Ticks; 203 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 204
205 if (timeLastChanged == 0) timeLastChanged = currentTime;
206 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
207
208 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 209 return true;
147 return false; 210 return false;
148 } 211 }
@@ -185,10 +248,10 @@ namespace OpenSim.Region.Framework.Scenes
185 248
186 private bool m_scriptListens_atTarget; 249 private bool m_scriptListens_atTarget;
187 private bool m_scriptListens_notAtTarget; 250 private bool m_scriptListens_notAtTarget;
188
189 private bool m_scriptListens_atRotTarget; 251 private bool m_scriptListens_atRotTarget;
190 private bool m_scriptListens_notAtRotTarget; 252 private bool m_scriptListens_notAtRotTarget;
191 253
254 public bool m_dupeInProgress = false;
192 internal Dictionary<UUID, string> m_savedScriptState; 255 internal Dictionary<UUID, string> m_savedScriptState;
193 256
194 #region Properties 257 #region Properties
@@ -228,7 +291,13 @@ namespace OpenSim.Region.Framework.Scenes
228 public virtual Quaternion Rotation 291 public virtual Quaternion Rotation
229 { 292 {
230 get { return m_rotation; } 293 get { return m_rotation; }
231 set { m_rotation = value; } 294 set {
295 foreach(SceneObjectPart p in m_parts.GetArray())
296 {
297 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
298 }
299 m_rotation = value;
300 }
232 } 301 }
233 302
234 public Quaternion GroupRotation 303 public Quaternion GroupRotation
@@ -302,7 +371,11 @@ namespace OpenSim.Region.Framework.Scenes
302 { 371 {
303 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 372 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
304 } 373 }
305 374
375 foreach (SceneObjectPart part in m_parts.GetArray())
376 {
377 part.IgnoreUndoUpdate = true;
378 }
306 if (RootPart.GetStatusSandbox()) 379 if (RootPart.GetStatusSandbox())
307 { 380 {
308 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 381 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -313,10 +386,31 @@ namespace OpenSim.Region.Framework.Scenes
313 return; 386 return;
314 } 387 }
315 } 388 }
316
317 SceneObjectPart[] parts = m_parts.GetArray(); 389 SceneObjectPart[] parts = m_parts.GetArray();
318 for (int i = 0; i < parts.Length; i++) 390 foreach (SceneObjectPart part in parts)
319 parts[i].GroupPosition = val; 391 {
392 part.IgnoreUndoUpdate = false;
393 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
394 part.GroupPosition = val;
395 if (!m_dupeInProgress)
396 {
397 part.TriggerScriptChangedEvent(Changed.POSITION);
398 }
399 }
400 if (!m_dupeInProgress)
401 {
402 foreach (ScenePresence av in m_linkedAvatars)
403 {
404 SceneObjectPart p;
405 if (m_parts.TryGetValue(av.LinkedPrim, out p))
406 {
407 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
408 av.AbsolutePosition += offset;
409 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
410 av.SendAvatarDataToAllAgents();
411 }
412 }
413 }
320 414
321 //if (m_rootPart.PhysActor != null) 415 //if (m_rootPart.PhysActor != null)
322 //{ 416 //{
@@ -467,6 +561,7 @@ namespace OpenSim.Region.Framework.Scenes
467 /// </summary> 561 /// </summary>
468 public SceneObjectGroup() 562 public SceneObjectGroup()
469 { 563 {
564
470 } 565 }
471 566
472 /// <summary> 567 /// <summary>
@@ -483,7 +578,7 @@ namespace OpenSim.Region.Framework.Scenes
483 /// Constructor. This object is added to the scene later via AttachToScene() 578 /// Constructor. This object is added to the scene later via AttachToScene()
484 /// </summary> 579 /// </summary>
485 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 580 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
486 { 581 {
487 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 582 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
488 } 583 }
489 584
@@ -531,6 +626,9 @@ namespace OpenSim.Region.Framework.Scenes
531 /// </summary> 626 /// </summary>
532 public virtual void AttachToBackup() 627 public virtual void AttachToBackup()
533 { 628 {
629 if (IsAttachment) return;
630 m_scene.SceneGraph.FireAttachToBackup(this);
631
534 if (InSceneBackup) 632 if (InSceneBackup)
535 { 633 {
536 //m_log.DebugFormat( 634 //m_log.DebugFormat(
@@ -646,9 +744,9 @@ namespace OpenSim.Region.Framework.Scenes
646 result.normal = inter.normal; 744 result.normal = inter.normal;
647 result.distance = inter.distance; 745 result.distance = inter.distance;
648 } 746 }
747
649 } 748 }
650 } 749 }
651
652 return result; 750 return result;
653 } 751 }
654 752
@@ -668,17 +766,19 @@ namespace OpenSim.Region.Framework.Scenes
668 minZ = 8192f; 766 minZ = 8192f;
669 767
670 SceneObjectPart[] parts = m_parts.GetArray(); 768 SceneObjectPart[] parts = m_parts.GetArray();
671 for (int i = 0; i < parts.Length; i++) 769 foreach (SceneObjectPart part in parts)
672 { 770 {
673 SceneObjectPart part = parts[i];
674
675 Vector3 worldPos = part.GetWorldPosition(); 771 Vector3 worldPos = part.GetWorldPosition();
676 Vector3 offset = worldPos - AbsolutePosition; 772 Vector3 offset = worldPos - AbsolutePosition;
677 Quaternion worldRot; 773 Quaternion worldRot;
678 if (part.ParentID == 0) 774 if (part.ParentID == 0)
775 {
679 worldRot = part.RotationOffset; 776 worldRot = part.RotationOffset;
777 }
680 else 778 else
779 {
681 worldRot = part.GetWorldRotation(); 780 worldRot = part.GetWorldRotation();
781 }
682 782
683 Vector3 frontTopLeft; 783 Vector3 frontTopLeft;
684 Vector3 frontTopRight; 784 Vector3 frontTopRight;
@@ -690,6 +790,8 @@ namespace OpenSim.Region.Framework.Scenes
690 Vector3 backBottomLeft; 790 Vector3 backBottomLeft;
691 Vector3 backBottomRight; 791 Vector3 backBottomRight;
692 792
793 // Vector3[] corners = new Vector3[8];
794
693 Vector3 orig = Vector3.Zero; 795 Vector3 orig = Vector3.Zero;
694 796
695 frontTopLeft.X = orig.X - (part.Scale.X / 2); 797 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -724,6 +826,38 @@ namespace OpenSim.Region.Framework.Scenes
724 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 826 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
725 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 827 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
726 828
829
830
831 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
832 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
833 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
834 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
835 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
836 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
837 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
838 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
839
840 //for (int i = 0; i < 8; i++)
841 //{
842 // corners[i] = corners[i] * worldRot;
843 // corners[i] += offset;
844
845 // if (corners[i].X > maxX)
846 // maxX = corners[i].X;
847 // if (corners[i].X < minX)
848 // minX = corners[i].X;
849
850 // if (corners[i].Y > maxY)
851 // maxY = corners[i].Y;
852 // if (corners[i].Y < minY)
853 // minY = corners[i].Y;
854
855 // if (corners[i].Z > maxZ)
856 // maxZ = corners[i].Y;
857 // if (corners[i].Z < minZ)
858 // minZ = corners[i].Z;
859 //}
860
727 frontTopLeft = frontTopLeft * worldRot; 861 frontTopLeft = frontTopLeft * worldRot;
728 frontTopRight = frontTopRight * worldRot; 862 frontTopRight = frontTopRight * worldRot;
729 frontBottomLeft = frontBottomLeft * worldRot; 863 frontBottomLeft = frontBottomLeft * worldRot;
@@ -745,6 +879,15 @@ namespace OpenSim.Region.Framework.Scenes
745 backTopLeft += offset; 879 backTopLeft += offset;
746 backTopRight += offset; 880 backTopRight += offset;
747 881
882 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
883 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
884 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
885 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
886 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
887 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
888 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
889 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
890
748 if (frontTopRight.X > maxX) 891 if (frontTopRight.X > maxX)
749 maxX = frontTopRight.X; 892 maxX = frontTopRight.X;
750 if (frontTopLeft.X > maxX) 893 if (frontTopLeft.X > maxX)
@@ -890,15 +1033,20 @@ namespace OpenSim.Region.Framework.Scenes
890 1033
891 public void SaveScriptedState(XmlTextWriter writer) 1034 public void SaveScriptedState(XmlTextWriter writer)
892 { 1035 {
1036 SaveScriptedState(writer, false);
1037 }
1038
1039 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1040 {
893 XmlDocument doc = new XmlDocument(); 1041 XmlDocument doc = new XmlDocument();
894 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1042 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
895 1043
896 SceneObjectPart[] parts = m_parts.GetArray(); 1044 SceneObjectPart[] parts = m_parts.GetArray();
897 for (int i = 0; i < parts.Length; i++) 1045 for (int i = 0; i < parts.Length; i++)
898 { 1046 {
899 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1047 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
900 foreach (KeyValuePair<UUID, string> kvp in pstates) 1048 foreach (KeyValuePair<UUID, string> kvp in pstates)
901 states.Add(kvp.Key, kvp.Value); 1049 states[kvp.Key] = kvp.Value;
902 } 1050 }
903 1051
904 if (states.Count > 0) 1052 if (states.Count > 0)
@@ -917,6 +1065,118 @@ namespace OpenSim.Region.Framework.Scenes
917 } 1065 }
918 } 1066 }
919 1067
1068 /// <summary>
1069 /// Add the avatar to this linkset (avatar is sat).
1070 /// </summary>
1071 /// <param name="agentID"></param>
1072 public void AddAvatar(UUID agentID)
1073 {
1074 ScenePresence presence;
1075 if (m_scene.TryGetScenePresence(agentID, out presence))
1076 {
1077 if (!m_linkedAvatars.Contains(presence))
1078 {
1079 m_linkedAvatars.Add(presence);
1080 }
1081 }
1082 }
1083
1084 /// <summary>
1085 /// Delete the avatar from this linkset (avatar is unsat).
1086 /// </summary>
1087 /// <param name="agentID"></param>
1088 public void DeleteAvatar(UUID agentID)
1089 {
1090 ScenePresence presence;
1091 if (m_scene.TryGetScenePresence(agentID, out presence))
1092 {
1093 if (m_linkedAvatars.Contains(presence))
1094 {
1095 m_linkedAvatars.Remove(presence);
1096 }
1097 }
1098 }
1099
1100 /// <summary>
1101 /// Returns the list of linked presences (avatars sat on this group)
1102 /// </summary>
1103 /// <param name="agentID"></param>
1104 public List<ScenePresence> GetLinkedAvatars()
1105 {
1106 return m_linkedAvatars;
1107 }
1108
1109 /// <summary>
1110 /// Attach this scene object to the given avatar.
1111 /// </summary>
1112 /// <param name="agentID"></param>
1113 /// <param name="attachmentpoint"></param>
1114 /// <param name="AttachOffset"></param>
1115 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent)
1116 {
1117 ScenePresence avatar = m_scene.GetScenePresence(agentID);
1118 if (avatar != null)
1119 {
1120 // don't attach attachments to child agents
1121 if (avatar.IsChildAgent) return;
1122
1123// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
1124
1125 DetachFromBackup();
1126
1127 // Remove from database and parcel prim count
1128 m_scene.DeleteFromStorage(UUID);
1129 m_scene.EventManager.TriggerParcelPrimCountTainted();
1130
1131 m_rootPart.AttachedAvatar = agentID;
1132
1133 //Anakin Lohner bug #3839
1134 lock (m_parts)
1135 {
1136 foreach (SceneObjectPart p in m_parts.GetArray())
1137 {
1138 p.AttachedAvatar = agentID;
1139 }
1140 }
1141
1142 if (m_rootPart.PhysActor != null)
1143 {
1144 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor);
1145 m_rootPart.PhysActor = null;
1146 }
1147
1148 AbsolutePosition = AttachOffset;
1149 m_rootPart.AttachedPos = AttachOffset;
1150 m_rootPart.IsAttachment = true;
1151
1152 m_rootPart.SetParentLocalId(avatar.LocalId);
1153 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
1154
1155 avatar.AddAttachment(this);
1156
1157 if (!silent)
1158 {
1159 // Killing it here will cause the client to deselect it
1160 // It then reappears on the avatar, deselected
1161 // through the full update below
1162 //
1163 if (IsSelected)
1164 {
1165 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1166 }
1167
1168 IsSelected = false; // fudge....
1169 ScheduleGroupForFullUpdate();
1170 }
1171 }
1172 else
1173 {
1174 m_log.WarnFormat(
1175 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1176 UUID, agentID, Scene.RegionInfo.RegionName);
1177 }
1178 }
1179
920 public byte GetAttachmentPoint() 1180 public byte GetAttachmentPoint()
921 { 1181 {
922 return m_rootPart.Shape.State; 1182 return m_rootPart.Shape.State;
@@ -1043,7 +1303,10 @@ namespace OpenSim.Region.Framework.Scenes
1043 public void AddPart(SceneObjectPart part) 1303 public void AddPart(SceneObjectPart part)
1044 { 1304 {
1045 part.SetParent(this); 1305 part.SetParent(this);
1046 part.LinkNum = m_parts.Add(part.UUID, part); 1306 m_parts.Add(part.UUID, part);
1307
1308 part.LinkNum = m_parts.Count;
1309
1047 if (part.LinkNum == 2 && RootPart != null) 1310 if (part.LinkNum == 2 && RootPart != null)
1048 RootPart.LinkNum = 1; 1311 RootPart.LinkNum = 1;
1049 } 1312 }
@@ -1127,7 +1390,7 @@ namespace OpenSim.Region.Framework.Scenes
1127 1390
1128 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1391 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1129 { 1392 {
1130 part.StoreUndoState(); 1393 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1131 part.OnGrab(offsetPos, remoteClient); 1394 part.OnGrab(offsetPos, remoteClient);
1132 } 1395 }
1133 1396
@@ -1147,6 +1410,11 @@ namespace OpenSim.Region.Framework.Scenes
1147 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1410 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1148 public void DeleteGroupFromScene(bool silent) 1411 public void DeleteGroupFromScene(bool silent)
1149 { 1412 {
1413 // We need to keep track of this state in case this group is still queued for backup.
1414 m_isDeleted = true;
1415
1416 DetachFromBackup();
1417
1150 SceneObjectPart[] parts = m_parts.GetArray(); 1418 SceneObjectPart[] parts = m_parts.GetArray();
1151 for (int i = 0; i < parts.Length; i++) 1419 for (int i = 0; i < parts.Length; i++)
1152 { 1420 {
@@ -1158,13 +1426,11 @@ namespace OpenSim.Region.Framework.Scenes
1158 avatar.StandUp(); 1426 avatar.StandUp();
1159 1427
1160 if (!silent) 1428 if (!silent)
1161 {
1162 part.UpdateFlag = 0; 1429 part.UpdateFlag = 0;
1163 if (part == m_rootPart)
1164 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1165 }
1166 }); 1430 });
1167 } 1431 }
1432
1433
1168 } 1434 }
1169 1435
1170 public void AddScriptLPS(int count) 1436 public void AddScriptLPS(int count)
@@ -1261,7 +1527,12 @@ namespace OpenSim.Region.Framework.Scenes
1261 1527
1262 public void SetOwnerId(UUID userId) 1528 public void SetOwnerId(UUID userId)
1263 { 1529 {
1264 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1530 ForEachPart(delegate(SceneObjectPart part)
1531 {
1532
1533 part.OwnerID = userId;
1534
1535 });
1265 } 1536 }
1266 1537
1267 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1538 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1293,11 +1564,17 @@ namespace OpenSim.Region.Framework.Scenes
1293 return; 1564 return;
1294 } 1565 }
1295 1566
1567 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1568 return;
1569
1296 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1570 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1297 // any exception propogate upwards. 1571 // any exception propogate upwards.
1298 try 1572 try
1299 { 1573 {
1300 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1574 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1575 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1576 m_scene.LoadingPrims) // Land may not be valid yet
1577
1301 { 1578 {
1302 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1579 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1303 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1580 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1322,6 +1599,7 @@ namespace OpenSim.Region.Framework.Scenes
1322 } 1599 }
1323 } 1600 }
1324 } 1601 }
1602
1325 } 1603 }
1326 1604
1327 if (HasGroupChanged) 1605 if (HasGroupChanged)
@@ -1329,6 +1607,20 @@ namespace OpenSim.Region.Framework.Scenes
1329 // don't backup while it's selected or you're asking for changes mid stream. 1607 // don't backup while it's selected or you're asking for changes mid stream.
1330 if (isTimeToPersist() || forcedBackup) 1608 if (isTimeToPersist() || forcedBackup)
1331 { 1609 {
1610 if (m_rootPart.PhysActor != null &&
1611 (!m_rootPart.PhysActor.IsPhysical))
1612 {
1613 // Possible ghost prim
1614 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1615 {
1616 foreach (SceneObjectPart part in m_parts.GetArray())
1617 {
1618 // Re-set physics actor positions and
1619 // orientations
1620 part.GroupPosition = m_rootPart.GroupPosition;
1621 }
1622 }
1623 }
1332// m_log.DebugFormat( 1624// m_log.DebugFormat(
1333// "[SCENE]: Storing {0}, {1} in {2}", 1625// "[SCENE]: Storing {0}, {1} in {2}",
1334// Name, UUID, m_scene.RegionInfo.RegionName); 1626// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1392,81 +1684,89 @@ namespace OpenSim.Region.Framework.Scenes
1392 /// <returns></returns> 1684 /// <returns></returns>
1393 public SceneObjectGroup Copy(bool userExposed) 1685 public SceneObjectGroup Copy(bool userExposed)
1394 { 1686 {
1395 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1687 SceneObjectGroup dupe;
1396 dupe.m_isBackedUp = false; 1688 try
1397 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1689 {
1398 1690 m_dupeInProgress = true;
1399 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1691 dupe = (SceneObjectGroup)MemberwiseClone();
1400 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1692 dupe.m_isBackedUp = false;
1401 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1693 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1402 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1403 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1404 // then restore it's attachment state
1405
1406 // This is only necessary when userExposed is false!
1407 1694
1408 bool previousAttachmentStatus = dupe.RootPart.IsAttachment; 1695 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1409 1696 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1410 if (!userExposed) 1697 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1411 dupe.RootPart.IsAttachment = true; 1698 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1699 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1700 // then restore it's attachment state
1412 1701
1413 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1702 // This is only necessary when userExposed is false!
1414 1703
1415 if (!userExposed) 1704 bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
1416 {
1417 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1418 }
1419 1705
1420 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1706 if (!userExposed)
1421 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1707 dupe.RootPart.IsAttachment = true;
1422 1708
1423 if (userExposed) 1709 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1424 dupe.m_rootPart.TrimPermissions();
1425 1710
1426 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1711 if (!userExposed)
1427
1428 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1429 { 1712 {
1430 return p1.LinkNum.CompareTo(p2.LinkNum); 1713 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1431 } 1714 }
1432 );
1433 1715
1434 foreach (SceneObjectPart part in partList) 1716 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1435 { 1717 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1436 if (part.UUID != m_rootPart.UUID) 1718
1719 if (userExposed)
1720 dupe.m_rootPart.TrimPermissions();
1721
1722 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1723
1724 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1725 {
1726 return p1.LinkNum.CompareTo(p2.LinkNum);
1727 }
1728 );
1729
1730 foreach (SceneObjectPart part in partList)
1437 { 1731 {
1438 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1732 if (part.UUID != m_rootPart.UUID)
1439 newPart.LinkNum = part.LinkNum; 1733 {
1440 } 1734 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1441 1735
1442 // Need to duplicate the physics actor as well 1736 newPart.LinkNum = part.LinkNum;
1443 if (part.PhysActor != null && userExposed) 1737 }
1738
1739 // Need to duplicate the physics actor as well
1740 if (part.PhysActor != null && userExposed)
1741 {
1742 PrimitiveBaseShape pbs = part.Shape;
1743
1744 part.PhysActor
1745 = m_scene.PhysicsScene.AddPrimShape(
1746 string.Format("{0}/{1}", part.Name, part.UUID),
1747 pbs,
1748 part.AbsolutePosition,
1749 part.Scale,
1750 part.RotationOffset,
1751 part.PhysActor.IsPhysical);
1752
1753 part.PhysActor.LocalID = part.LocalId;
1754 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1755 }
1756 }
1757 if (userExposed)
1444 { 1758 {
1445 PrimitiveBaseShape pbs = part.Shape; 1759 dupe.UpdateParentIDs();
1446 1760 dupe.HasGroupChanged = true;
1447 part.PhysActor 1761 dupe.AttachToBackup();
1448 = m_scene.PhysicsScene.AddPrimShape( 1762
1449 string.Format("{0}/{1}", part.Name, part.UUID), 1763 ScheduleGroupForFullUpdate();
1450 pbs,
1451 part.AbsolutePosition,
1452 part.Scale,
1453 part.RotationOffset,
1454 part.PhysActor.IsPhysical);
1455
1456 part.PhysActor.LocalID = part.LocalId;
1457 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1458 } 1764 }
1459 } 1765 }
1460 1766 finally
1461 if (userExposed)
1462 { 1767 {
1463 dupe.UpdateParentIDs(); 1768 m_dupeInProgress = false;
1464 dupe.HasGroupChanged = true;
1465 dupe.AttachToBackup();
1466
1467 ScheduleGroupForFullUpdate();
1468 } 1769 }
1469
1470 return dupe; 1770 return dupe;
1471 } 1771 }
1472 1772
@@ -1657,13 +1957,40 @@ namespace OpenSim.Region.Framework.Scenes
1657 } 1957 }
1658 } 1958 }
1659 1959
1960 public void rotLookAt(Quaternion target, float strength, float damping)
1961 {
1962 SceneObjectPart rootpart = m_rootPart;
1963 if (rootpart != null)
1964 {
1965 if (IsAttachment)
1966 {
1967 /*
1968 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1969 if (avatar != null)
1970 {
1971 Rotate the Av?
1972 } */
1973 }
1974 else
1975 {
1976 if (rootpart.PhysActor != null)
1977 { // APID must be implemented in your physics system for this to function.
1978 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1979 rootpart.PhysActor.APIDStrength = strength;
1980 rootpart.PhysActor.APIDDamping = damping;
1981 rootpart.PhysActor.APIDActive = true;
1982 }
1983 }
1984 }
1985 }
1986
1660 public void stopLookAt() 1987 public void stopLookAt()
1661 { 1988 {
1662 SceneObjectPart rootpart = m_rootPart; 1989 SceneObjectPart rootpart = m_rootPart;
1663 if (rootpart != null) 1990 if (rootpart != null)
1664 { 1991 {
1665 if (rootpart.PhysActor != null) 1992 if (rootpart.PhysActor != null)
1666 { 1993 { // APID must be implemented in your physics system for this to function.
1667 rootpart.PhysActor.APIDActive = false; 1994 rootpart.PhysActor.APIDActive = false;
1668 } 1995 }
1669 } 1996 }
@@ -1729,6 +2056,8 @@ namespace OpenSim.Region.Framework.Scenes
1729 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2056 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1730 { 2057 {
1731 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2058 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2059 newPart.SetParent(this);
2060
1732 AddPart(newPart); 2061 AddPart(newPart);
1733 2062
1734 SetPartAsNonRoot(newPart); 2063 SetPartAsNonRoot(newPart);
@@ -1875,11 +2204,11 @@ namespace OpenSim.Region.Framework.Scenes
1875 /// Immediately send a full update for this scene object. 2204 /// Immediately send a full update for this scene object.
1876 /// </summary> 2205 /// </summary>
1877 public void SendGroupFullUpdate() 2206 public void SendGroupFullUpdate()
1878 { 2207 {
1879 if (IsDeleted) 2208 if (IsDeleted)
1880 return; 2209 return;
1881 2210
1882// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2211// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1883 2212
1884 RootPart.SendFullUpdateToAllClients(); 2213 RootPart.SendFullUpdateToAllClients();
1885 2214
@@ -2068,12 +2397,15 @@ namespace OpenSim.Region.Framework.Scenes
2068 part.LinkNum += objectGroup.PrimCount; 2397 part.LinkNum += objectGroup.PrimCount;
2069 } 2398 }
2070 } 2399 }
2400 }
2071 2401
2072 linkPart.LinkNum = 2; 2402 linkPart.LinkNum = 2;
2073 2403
2074 linkPart.SetParent(this); 2404 linkPart.SetParent(this);
2075 linkPart.CreateSelected = true; 2405 linkPart.CreateSelected = true;
2076 2406
2407 lock (m_parts.SyncRoot)
2408 {
2077 //if (linkPart.PhysActor != null) 2409 //if (linkPart.PhysActor != null)
2078 //{ 2410 //{
2079 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2411 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2231,6 +2563,8 @@ namespace OpenSim.Region.Framework.Scenes
2231 /// <param name="objectGroup"></param> 2563 /// <param name="objectGroup"></param>
2232 public virtual void DetachFromBackup() 2564 public virtual void DetachFromBackup()
2233 { 2565 {
2566 m_scene.SceneGraph.FireDetachFromBackup(this);
2567
2234 if (m_isBackedUp) 2568 if (m_isBackedUp)
2235 m_scene.EventManager.OnBackup -= ProcessBackup; 2569 m_scene.EventManager.OnBackup -= ProcessBackup;
2236 2570
@@ -2535,6 +2869,17 @@ namespace OpenSim.Region.Framework.Scenes
2535 } 2869 }
2536 } 2870 }
2537 2871
2872
2873
2874 /// <summary>
2875 /// Gets the number of parts
2876 /// </summary>
2877 /// <returns></returns>
2878 public int GetPartCount()
2879 {
2880 return Parts.Count();
2881 }
2882
2538 /// <summary> 2883 /// <summary>
2539 /// Update the texture entry for this part 2884 /// Update the texture entry for this part
2540 /// </summary> 2885 /// </summary>
@@ -2596,11 +2941,9 @@ namespace OpenSim.Region.Framework.Scenes
2596 scale.Y = m_scene.m_maxNonphys; 2941 scale.Y = m_scene.m_maxNonphys;
2597 if (scale.Z > m_scene.m_maxNonphys) 2942 if (scale.Z > m_scene.m_maxNonphys)
2598 scale.Z = m_scene.m_maxNonphys; 2943 scale.Z = m_scene.m_maxNonphys;
2599
2600 SceneObjectPart part = GetChildPart(localID); 2944 SceneObjectPart part = GetChildPart(localID);
2601 if (part != null) 2945 if (part != null)
2602 { 2946 {
2603 part.Resize(scale);
2604 if (part.PhysActor != null) 2947 if (part.PhysActor != null)
2605 { 2948 {
2606 if (part.PhysActor.IsPhysical) 2949 if (part.PhysActor.IsPhysical)
@@ -2615,7 +2958,7 @@ namespace OpenSim.Region.Framework.Scenes
2615 part.PhysActor.Size = scale; 2958 part.PhysActor.Size = scale;
2616 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2959 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2617 } 2960 }
2618 //if (part.UUID != m_rootPart.UUID) 2961 part.Resize(scale);
2619 2962
2620 HasGroupChanged = true; 2963 HasGroupChanged = true;
2621 part.TriggerScriptChangedEvent(Changed.SCALE); 2964 part.TriggerScriptChangedEvent(Changed.SCALE);
@@ -2638,7 +2981,6 @@ namespace OpenSim.Region.Framework.Scenes
2638 SceneObjectPart part = GetChildPart(localID); 2981 SceneObjectPart part = GetChildPart(localID);
2639 if (part != null) 2982 if (part != null)
2640 { 2983 {
2641 part.IgnoreUndoUpdate = true;
2642 if (scale.X > m_scene.m_maxNonphys) 2984 if (scale.X > m_scene.m_maxNonphys)
2643 scale.X = m_scene.m_maxNonphys; 2985 scale.X = m_scene.m_maxNonphys;
2644 if (scale.Y > m_scene.m_maxNonphys) 2986 if (scale.Y > m_scene.m_maxNonphys)
@@ -2675,7 +3017,7 @@ namespace OpenSim.Region.Framework.Scenes
2675 3017
2676 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3018 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2677 { 3019 {
2678 if (oldSize.X * x > m_scene.m_maxPhys) 3020 if (oldSize.X*x > m_scene.m_maxPhys)
2679 { 3021 {
2680 f = m_scene.m_maxPhys / oldSize.X; 3022 f = m_scene.m_maxPhys / oldSize.X;
2681 a = f / x; 3023 a = f / x;
@@ -2683,7 +3025,7 @@ namespace OpenSim.Region.Framework.Scenes
2683 y *= a; 3025 y *= a;
2684 z *= a; 3026 z *= a;
2685 } 3027 }
2686 if (oldSize.Y * y > m_scene.m_maxPhys) 3028 if (oldSize.Y*y > m_scene.m_maxPhys)
2687 { 3029 {
2688 f = m_scene.m_maxPhys / oldSize.Y; 3030 f = m_scene.m_maxPhys / oldSize.Y;
2689 a = f / y; 3031 a = f / y;
@@ -2691,7 +3033,7 @@ namespace OpenSim.Region.Framework.Scenes
2691 y *= a; 3033 y *= a;
2692 z *= a; 3034 z *= a;
2693 } 3035 }
2694 if (oldSize.Z * z > m_scene.m_maxPhys) 3036 if (oldSize.Z*z > m_scene.m_maxPhys)
2695 { 3037 {
2696 f = m_scene.m_maxPhys / oldSize.Z; 3038 f = m_scene.m_maxPhys / oldSize.Z;
2697 a = f / z; 3039 a = f / z;
@@ -2702,7 +3044,7 @@ namespace OpenSim.Region.Framework.Scenes
2702 } 3044 }
2703 else 3045 else
2704 { 3046 {
2705 if (oldSize.X * x > m_scene.m_maxNonphys) 3047 if (oldSize.X*x > m_scene.m_maxNonphys)
2706 { 3048 {
2707 f = m_scene.m_maxNonphys / oldSize.X; 3049 f = m_scene.m_maxNonphys / oldSize.X;
2708 a = f / x; 3050 a = f / x;
@@ -2710,7 +3052,7 @@ namespace OpenSim.Region.Framework.Scenes
2710 y *= a; 3052 y *= a;
2711 z *= a; 3053 z *= a;
2712 } 3054 }
2713 if (oldSize.Y * y > m_scene.m_maxNonphys) 3055 if (oldSize.Y*y > m_scene.m_maxNonphys)
2714 { 3056 {
2715 f = m_scene.m_maxNonphys / oldSize.Y; 3057 f = m_scene.m_maxNonphys / oldSize.Y;
2716 a = f / y; 3058 a = f / y;
@@ -2718,7 +3060,7 @@ namespace OpenSim.Region.Framework.Scenes
2718 y *= a; 3060 y *= a;
2719 z *= a; 3061 z *= a;
2720 } 3062 }
2721 if (oldSize.Z * z > m_scene.m_maxNonphys) 3063 if (oldSize.Z*z > m_scene.m_maxNonphys)
2722 { 3064 {
2723 f = m_scene.m_maxNonphys / oldSize.Z; 3065 f = m_scene.m_maxNonphys / oldSize.Z;
2724 a = f / z; 3066 a = f / z;
@@ -2728,7 +3070,6 @@ namespace OpenSim.Region.Framework.Scenes
2728 } 3070 }
2729 } 3071 }
2730 obPart.IgnoreUndoUpdate = false; 3072 obPart.IgnoreUndoUpdate = false;
2731 obPart.StoreUndoState();
2732 } 3073 }
2733 } 3074 }
2734 } 3075 }
@@ -2736,8 +3077,13 @@ namespace OpenSim.Region.Framework.Scenes
2736 Vector3 prevScale = part.Scale; 3077 Vector3 prevScale = part.Scale;
2737 prevScale.X *= x; 3078 prevScale.X *= x;
2738 prevScale.Y *= y; 3079 prevScale.Y *= y;
2739 prevScale.Z *= z; 3080 prevScale.Z *= z;;
3081
3082 part.IgnoreUndoUpdate = false;
3083 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3084 part.IgnoreUndoUpdate = true;
2740 part.Resize(prevScale); 3085 part.Resize(prevScale);
3086 part.IgnoreUndoUpdate = false;
2741 3087
2742 parts = m_parts.GetArray(); 3088 parts = m_parts.GetArray();
2743 for (int i = 0; i < parts.Length; i++) 3089 for (int i = 0; i < parts.Length; i++)
@@ -2746,19 +3092,26 @@ namespace OpenSim.Region.Framework.Scenes
2746 obPart.IgnoreUndoUpdate = true; 3092 obPart.IgnoreUndoUpdate = true;
2747 if (obPart.UUID != m_rootPart.UUID) 3093 if (obPart.UUID != m_rootPart.UUID)
2748 { 3094 {
2749 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3095 if (obPart.UUID != m_rootPart.UUID)
2750 currentpos.X *= x; 3096 {
2751 currentpos.Y *= y; 3097 obPart.IgnoreUndoUpdate = false;
2752 currentpos.Z *= z; 3098 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
2753 Vector3 newSize = new Vector3(obPart.Scale); 3099 obPart.IgnoreUndoUpdate = true;
2754 newSize.X *= x; 3100
2755 newSize.Y *= y; 3101 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2756 newSize.Z *= z; 3102 currentpos.X *= x;
2757 obPart.Resize(newSize); 3103 currentpos.Y *= y;
2758 obPart.UpdateOffSet(currentpos); 3104 currentpos.Z *= z;
3105 Vector3 newSize = new Vector3(obPart.Scale);
3106 newSize.X *= x;
3107 newSize.Y *= y;
3108 newSize.Z *= z;
3109 obPart.Resize(newSize);
3110 obPart.UpdateOffSet(currentpos);
3111 }
3112 obPart.IgnoreUndoUpdate = false;
2759 } 3113 }
2760 obPart.IgnoreUndoUpdate = false; 3114 obPart.IgnoreUndoUpdate = false;
2761 obPart.StoreUndoState();
2762 } 3115 }
2763 3116
2764 if (part.PhysActor != null) 3117 if (part.PhysActor != null)
@@ -2768,7 +3121,6 @@ namespace OpenSim.Region.Framework.Scenes
2768 } 3121 }
2769 3122
2770 part.IgnoreUndoUpdate = false; 3123 part.IgnoreUndoUpdate = false;
2771 part.StoreUndoState();
2772 HasGroupChanged = true; 3124 HasGroupChanged = true;
2773 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); 3125 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
2774 ScheduleGroupForTerseUpdate(); 3126 ScheduleGroupForTerseUpdate();
@@ -2785,14 +3137,11 @@ namespace OpenSim.Region.Framework.Scenes
2785 /// <param name="pos"></param> 3137 /// <param name="pos"></param>
2786 public void UpdateGroupPosition(Vector3 pos) 3138 public void UpdateGroupPosition(Vector3 pos)
2787 { 3139 {
2788 SceneObjectPart[] parts = m_parts.GetArray();
2789 for (int i = 0; i < parts.Length; i++)
2790 parts[i].StoreUndoState();
2791
2792 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3140 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2793 { 3141 {
2794 if (IsAttachment) 3142 if (IsAttachment)
2795 { 3143 {
3144 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2796 m_rootPart.AttachedPos = pos; 3145 m_rootPart.AttachedPos = pos;
2797 } 3146 }
2798 if (RootPart.GetStatusSandbox()) 3147 if (RootPart.GetStatusSandbox())
@@ -2826,7 +3175,7 @@ namespace OpenSim.Region.Framework.Scenes
2826 3175
2827 SceneObjectPart[] parts = m_parts.GetArray(); 3176 SceneObjectPart[] parts = m_parts.GetArray();
2828 for (int i = 0; i < parts.Length; i++) 3177 for (int i = 0; i < parts.Length; i++)
2829 parts[i].StoreUndoState(); 3178 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2830 3179
2831 if (part != null) 3180 if (part != null)
2832 { 3181 {
@@ -2851,7 +3200,7 @@ namespace OpenSim.Region.Framework.Scenes
2851 { 3200 {
2852 SceneObjectPart[] parts = m_parts.GetArray(); 3201 SceneObjectPart[] parts = m_parts.GetArray();
2853 for (int i = 0; i < parts.Length; i++) 3202 for (int i = 0; i < parts.Length; i++)
2854 parts[i].StoreUndoState(); 3203 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2855 3204
2856 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3205 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2857 Vector3 oldPos = 3206 Vector3 oldPos =
@@ -2872,10 +3221,27 @@ namespace OpenSim.Region.Framework.Scenes
2872 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3221 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2873 } 3222 }
2874 3223
2875 AbsolutePosition = newPos; 3224 //We have to set undoing here because otherwise an undo state will be saved
3225 if (!m_rootPart.Undoing)
3226 {
3227 m_rootPart.Undoing = true;
3228 AbsolutePosition = newPos;
3229 m_rootPart.Undoing = false;
3230 }
3231 else
3232 {
3233 AbsolutePosition = newPos;
3234 }
2876 3235
2877 HasGroupChanged = true; 3236 HasGroupChanged = true;
2878 ScheduleGroupForTerseUpdate(); 3237 if (m_rootPart.Undoing)
3238 {
3239 ScheduleGroupForFullUpdate();
3240 }
3241 else
3242 {
3243 ScheduleGroupForTerseUpdate();
3244 }
2879 } 3245 }
2880 3246
2881 public void OffsetForNewRegion(Vector3 offset) 3247 public void OffsetForNewRegion(Vector3 offset)
@@ -2895,7 +3261,7 @@ namespace OpenSim.Region.Framework.Scenes
2895 { 3261 {
2896 SceneObjectPart[] parts = m_parts.GetArray(); 3262 SceneObjectPart[] parts = m_parts.GetArray();
2897 for (int i = 0; i < parts.Length; i++) 3263 for (int i = 0; i < parts.Length; i++)
2898 parts[i].StoreUndoState(); 3264 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2899 3265
2900 m_rootPart.UpdateRotation(rot); 3266 m_rootPart.UpdateRotation(rot);
2901 3267
@@ -2919,7 +3285,7 @@ namespace OpenSim.Region.Framework.Scenes
2919 { 3285 {
2920 SceneObjectPart[] parts = m_parts.GetArray(); 3286 SceneObjectPart[] parts = m_parts.GetArray();
2921 for (int i = 0; i < parts.Length; i++) 3287 for (int i = 0; i < parts.Length; i++)
2922 parts[i].StoreUndoState(); 3288 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2923 3289
2924 m_rootPart.UpdateRotation(rot); 3290 m_rootPart.UpdateRotation(rot);
2925 3291
@@ -2944,10 +3310,9 @@ namespace OpenSim.Region.Framework.Scenes
2944 public void UpdateSingleRotation(Quaternion rot, uint localID) 3310 public void UpdateSingleRotation(Quaternion rot, uint localID)
2945 { 3311 {
2946 SceneObjectPart part = GetChildPart(localID); 3312 SceneObjectPart part = GetChildPart(localID);
2947
2948 SceneObjectPart[] parts = m_parts.GetArray(); 3313 SceneObjectPart[] parts = m_parts.GetArray();
2949 for (int i = 0; i < parts.Length; i++) 3314 for (int i = 0; i < parts.Length; i++)
2950 parts[i].StoreUndoState(); 3315 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2951 3316
2952 if (part != null) 3317 if (part != null)
2953 { 3318 {
@@ -2975,15 +3340,24 @@ namespace OpenSim.Region.Framework.Scenes
2975 if (part.UUID == m_rootPart.UUID) 3340 if (part.UUID == m_rootPart.UUID)
2976 { 3341 {
2977 UpdateRootRotation(rot); 3342 UpdateRootRotation(rot);
2978 AbsolutePosition = pos; 3343 if (!m_rootPart.Undoing)
3344 {
3345 m_rootPart.Undoing = true;
3346 AbsolutePosition = pos;
3347 m_rootPart.Undoing = false;
3348 }
3349 else
3350 {
3351 AbsolutePosition = pos;
3352 }
2979 } 3353 }
2980 else 3354 else
2981 { 3355 {
3356 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2982 part.IgnoreUndoUpdate = true; 3357 part.IgnoreUndoUpdate = true;
2983 part.UpdateRotation(rot); 3358 part.UpdateRotation(rot);
2984 part.OffsetPosition = pos; 3359 part.OffsetPosition = pos;
2985 part.IgnoreUndoUpdate = false; 3360 part.IgnoreUndoUpdate = false;
2986 part.StoreUndoState();
2987 } 3361 }
2988 } 3362 }
2989 } 3363 }
@@ -2997,7 +3371,13 @@ namespace OpenSim.Region.Framework.Scenes
2997 Quaternion axRot = rot; 3371 Quaternion axRot = rot;
2998 Quaternion oldParentRot = m_rootPart.RotationOffset; 3372 Quaternion oldParentRot = m_rootPart.RotationOffset;
2999 3373
3000 m_rootPart.StoreUndoState(); 3374 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3375 bool cancelUndo = false;
3376 if (!m_rootPart.Undoing)
3377 {
3378 m_rootPart.Undoing = true;
3379 cancelUndo = true;
3380 }
3001 m_rootPart.UpdateRotation(rot); 3381 m_rootPart.UpdateRotation(rot);
3002 if (m_rootPart.PhysActor != null) 3382 if (m_rootPart.PhysActor != null)
3003 { 3383 {
@@ -3021,17 +3401,12 @@ namespace OpenSim.Region.Framework.Scenes
3021 newRot *= Quaternion.Inverse(axRot); 3401 newRot *= Quaternion.Inverse(axRot);
3022 prim.RotationOffset = newRot; 3402 prim.RotationOffset = newRot;
3023 prim.ScheduleTerseUpdate(); 3403 prim.ScheduleTerseUpdate();
3404 prim.IgnoreUndoUpdate = false;
3024 } 3405 }
3025 } 3406 }
3026 3407 if (cancelUndo == true)
3027 for (int i = 0; i < parts.Length; i++)
3028 { 3408 {
3029 SceneObjectPart childpart = parts[i]; 3409 m_rootPart.Undoing = false;
3030 if (childpart != m_rootPart)
3031 {
3032 childpart.IgnoreUndoUpdate = false;
3033 childpart.StoreUndoState();
3034 }
3035 } 3410 }
3036 3411
3037 m_rootPart.ScheduleTerseUpdate(); 3412 m_rootPart.ScheduleTerseUpdate();
@@ -3257,7 +3632,6 @@ namespace OpenSim.Region.Framework.Scenes
3257 public float GetMass() 3632 public float GetMass()
3258 { 3633 {
3259 float retmass = 0f; 3634 float retmass = 0f;
3260
3261 SceneObjectPart[] parts = m_parts.GetArray(); 3635 SceneObjectPart[] parts = m_parts.GetArray();
3262 for (int i = 0; i < parts.Length; i++) 3636 for (int i = 0; i < parts.Length; i++)
3263 retmass += parts[i].GetMass(); 3637 retmass += parts[i].GetMass();
@@ -3373,6 +3747,14 @@ namespace OpenSim.Region.Framework.Scenes
3373 SetFromItemID(uuid); 3747 SetFromItemID(uuid);
3374 } 3748 }
3375 3749
3750 public void ResetOwnerChangeFlag()
3751 {
3752 ForEachPart(delegate(SceneObjectPart part)
3753 {
3754 part.ResetOwnerChangeFlag();
3755 });
3756 }
3757
3376 #endregion 3758 #endregion
3377 } 3759 }
3378} 3760}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index f87056e..db60ae3 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -61,7 +61,8 @@ namespace OpenSim.Region.Framework.Scenes
61 TELEPORT = 512, 61 TELEPORT = 512,
62 REGION_RESTART = 1024, 62 REGION_RESTART = 1024,
63 MEDIA = 2048, 63 MEDIA = 2048,
64 ANIMATION = 16384 64 ANIMATION = 16384,
65 POSITION = 32768
65 } 66 }
66 67
67 // I don't really know where to put this except here. 68 // I don't really know where to put this except here.
@@ -145,10 +146,10 @@ namespace OpenSim.Region.Framework.Scenes
145 public Vector3 StatusSandboxPos; 146 public Vector3 StatusSandboxPos;
146 147
147 // TODO: This needs to be persisted in next XML version update! 148 // TODO: This needs to be persisted in next XML version update!
148 149 [XmlIgnore]
149 public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; 150 public int[] PayPrice = {-2,-2,-2,-2,-2};
150 151
151 152 [XmlIgnore]
152 public PhysicsActor PhysActor 153 public PhysicsActor PhysActor
153 { 154 {
154 get { return m_physActor; } 155 get { return m_physActor; }
@@ -190,7 +191,15 @@ namespace OpenSim.Region.Framework.Scenes
190 191
191 public UUID FromFolderID; 192 public UUID FromFolderID;
192 193
193 194 // The following two are to hold the attachment data
195 // while an object is inworld
196 [XmlIgnore]
197 public byte AttachPoint = 0;
198
199 [XmlIgnore]
200 public Vector3 AttachOffset = Vector3.Zero;
201
202 [XmlIgnore]
194 public int STATUS_ROTATE_X; 203 public int STATUS_ROTATE_X;
195 204
196 205
@@ -285,6 +294,7 @@ namespace OpenSim.Region.Framework.Scenes
285 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 294 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
286 private Vector3 m_sitTargetPosition; 295 private Vector3 m_sitTargetPosition;
287 private string m_sitAnimation = "SIT"; 296 private string m_sitAnimation = "SIT";
297 private bool m_occupied; // KF if any av is sitting on this prim
288 private string m_text = String.Empty; 298 private string m_text = String.Empty;
289 private string m_touchName = String.Empty; 299 private string m_touchName = String.Empty;
290 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 300 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -374,7 +384,7 @@ namespace OpenSim.Region.Framework.Scenes
374 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 384 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
375 Quaternion rotationOffset, Vector3 offsetPosition) 385 Quaternion rotationOffset, Vector3 offsetPosition)
376 { 386 {
377 m_name = "Primitive"; 387 m_name = "Object";
378 388
379 Rezzed = DateTime.UtcNow; 389 Rezzed = DateTime.UtcNow;
380 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 390 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
@@ -430,7 +440,7 @@ namespace OpenSim.Region.Framework.Scenes
430 private uint _ownerMask = (uint)PermissionMask.All; 440 private uint _ownerMask = (uint)PermissionMask.All;
431 private uint _groupMask = (uint)PermissionMask.None; 441 private uint _groupMask = (uint)PermissionMask.None;
432 private uint _everyoneMask = (uint)PermissionMask.None; 442 private uint _everyoneMask = (uint)PermissionMask.None;
433 private uint _nextOwnerMask = (uint)PermissionMask.All; 443 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
434 private PrimFlags _flags = PrimFlags.None; 444 private PrimFlags _flags = PrimFlags.None;
435 private DateTime m_expires; 445 private DateTime m_expires;
436 private DateTime m_rezzed; 446 private DateTime m_rezzed;
@@ -529,12 +539,16 @@ namespace OpenSim.Region.Framework.Scenes
529 } 539 }
530 540
531 /// <value> 541 /// <value>
532 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 542 /// Get the inventory list
533 /// </value> 543 /// </value>
534 public TaskInventoryDictionary TaskInventory 544 public TaskInventoryDictionary TaskInventory
535 { 545 {
536 get { return m_inventory.Items; } 546 get {
537 set { m_inventory.Items = value; } 547 return m_inventory.Items;
548 }
549 set {
550 m_inventory.Items = value;
551 }
538 } 552 }
539 553
540 /// <summary> 554 /// <summary>
@@ -674,14 +688,12 @@ namespace OpenSim.Region.Framework.Scenes
674 set { m_LoopSoundSlavePrims = value; } 688 set { m_LoopSoundSlavePrims = value; }
675 } 689 }
676 690
677
678 public Byte[] TextureAnimation 691 public Byte[] TextureAnimation
679 { 692 {
680 get { return m_TextureAnimation; } 693 get { return m_TextureAnimation; }
681 set { m_TextureAnimation = value; } 694 set { m_TextureAnimation = value; }
682 } 695 }
683 696
684
685 public Byte[] ParticleSystem 697 public Byte[] ParticleSystem
686 { 698 {
687 get { return m_particleSystem; } 699 get { return m_particleSystem; }
@@ -735,7 +747,6 @@ namespace OpenSim.Region.Framework.Scenes
735 set 747 set
736 { 748 {
737 m_groupPosition = value; 749 m_groupPosition = value;
738
739 PhysicsActor actor = PhysActor; 750 PhysicsActor actor = PhysActor;
740 if (actor != null) 751 if (actor != null)
741 { 752 {
@@ -755,25 +766,13 @@ namespace OpenSim.Region.Framework.Scenes
755 766
756 // Tell the physics engines that this prim changed. 767 // Tell the physics engines that this prim changed.
757 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 768 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
769
758 } 770 }
759 catch (Exception e) 771 catch (Exception e)
760 { 772 {
761 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 773 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
762 } 774 }
763 } 775 }
764
765 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
766 if (m_sitTargetAvatar != UUID.Zero)
767 {
768 if (m_parentGroup != null) // TODO can there be a SOP without a SOG?
769 {
770 ScenePresence avatar;
771 if (m_parentGroup.Scene.TryGetScenePresence(m_sitTargetAvatar, out avatar))
772 {
773 avatar.ParentPosition = GetWorldPosition();
774 }
775 }
776 }
777 } 776 }
778 } 777 }
779 778
@@ -782,7 +781,8 @@ namespace OpenSim.Region.Framework.Scenes
782 get { return m_offsetPosition; } 781 get { return m_offsetPosition; }
783 set 782 set
784 { 783 {
785 StoreUndoState(); 784 Vector3 oldpos = m_offsetPosition;
785 StoreUndoState(UndoType.STATE_PRIM_POSITION);
786 m_offsetPosition = value; 786 m_offsetPosition = value;
787 787
788 if (ParentGroup != null && !ParentGroup.IsDeleted) 788 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -796,7 +796,22 @@ namespace OpenSim.Region.Framework.Scenes
796 // Tell the physics engines that this prim changed. 796 // Tell the physics engines that this prim changed.
797 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 797 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
798 } 798 }
799
800 if (!m_parentGroup.m_dupeInProgress)
801 {
802 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
803 foreach (ScenePresence av in avs)
804 {
805 if (av.LinkedPrim == m_uuid)
806 {
807 Vector3 offset = (m_offsetPosition - oldpos);
808 av.OffsetPosition += offset;
809 av.SendAvatarDataToAllAgents();
810 }
811 }
812 }
799 } 813 }
814 TriggerScriptChangedEvent(Changed.POSITION);
800 } 815 }
801 } 816 }
802 817
@@ -838,7 +853,7 @@ namespace OpenSim.Region.Framework.Scenes
838 853
839 set 854 set
840 { 855 {
841 StoreUndoState(); 856 StoreUndoState(UndoType.STATE_PRIM_ROTATION);
842 m_rotationOffset = value; 857 m_rotationOffset = value;
843 858
844 PhysicsActor actor = PhysActor; 859 PhysicsActor actor = PhysActor;
@@ -922,7 +937,16 @@ namespace OpenSim.Region.Framework.Scenes
922 /// <summary></summary> 937 /// <summary></summary>
923 public Vector3 Acceleration 938 public Vector3 Acceleration
924 { 939 {
925 get { return m_acceleration; } 940 get
941 {
942 PhysicsActor actor = PhysActor;
943 if (actor != null)
944 {
945 m_acceleration = actor.Acceleration;
946 }
947 return m_acceleration;
948 }
949
926 set { m_acceleration = value; } 950 set { m_acceleration = value; }
927 } 951 }
928 952
@@ -1013,7 +1037,7 @@ namespace OpenSim.Region.Framework.Scenes
1013 get { return m_shape.Scale; } 1037 get { return m_shape.Scale; }
1014 set 1038 set
1015 { 1039 {
1016 StoreUndoState(); 1040 StoreUndoState(UndoType.STATE_PRIM_SCALE);
1017 if (m_shape != null) 1041 if (m_shape != null)
1018 { 1042 {
1019 m_shape.Scale = value; 1043 m_shape.Scale = value;
@@ -1081,9 +1105,10 @@ namespace OpenSim.Region.Framework.Scenes
1081 { 1105 {
1082 get { 1106 get {
1083 if (IsAttachment) 1107 if (IsAttachment)
1084 return GroupPosition; 1108 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1085 1109
1086 return m_offsetPosition + m_groupPosition; } 1110// return m_offsetPosition + m_groupPosition; }
1111 return m_groupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset) ; } //KF: Rotation was ignored!
1087 } 1112 }
1088 1113
1089 public SceneObjectGroup ParentGroup 1114 public SceneObjectGroup ParentGroup
@@ -1242,6 +1267,13 @@ namespace OpenSim.Region.Framework.Scenes
1242 _flags = value; 1267 _flags = value;
1243 } 1268 }
1244 } 1269 }
1270
1271 [XmlIgnore]
1272 public bool IsOccupied // KF If an av is sittingon this prim
1273 {
1274 get { return m_occupied; }
1275 set { m_occupied = value; }
1276 }
1245 1277
1246 1278
1247 public UUID SitTargetAvatar 1279 public UUID SitTargetAvatar
@@ -1317,14 +1349,6 @@ namespace OpenSim.Region.Framework.Scenes
1317 } 1349 }
1318 } 1350 }
1319 1351
1320 /// <summary>
1321 /// Clear all pending updates of parts to clients
1322 /// </summary>
1323 private void ClearUpdateSchedule()
1324 {
1325 m_updateFlag = 0;
1326 }
1327
1328 private void SendObjectPropertiesToClient(UUID AgentID) 1352 private void SendObjectPropertiesToClient(UUID AgentID)
1329 { 1353 {
1330 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1354 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1575,14 +1599,21 @@ namespace OpenSim.Region.Framework.Scenes
1575 // or flexible 1599 // or flexible
1576 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) 1600 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
1577 { 1601 {
1578 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 1602 try
1579 string.Format("{0}/{1}", Name, UUID), 1603 {
1580 Shape, 1604 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1581 AbsolutePosition, 1605 string.Format("{0}/{1}", Name, UUID),
1582 Scale, 1606 Shape,
1583 RotationOffset, 1607 AbsolutePosition,
1584 RigidBody); 1608 Scale,
1585 1609 RotationOffset,
1610 RigidBody);
1611 }
1612 catch
1613 {
1614 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
1615 PhysActor = null;
1616 }
1586 // Basic Physics returns null.. joy joy joy. 1617 // Basic Physics returns null.. joy joy joy.
1587 if (PhysActor != null) 1618 if (PhysActor != null)
1588 { 1619 {
@@ -1610,7 +1641,7 @@ namespace OpenSim.Region.Framework.Scenes
1610 { 1641 {
1611 m_redo.Clear(); 1642 m_redo.Clear();
1612 } 1643 }
1613 StoreUndoState(); 1644 StoreUndoState(UndoType.STATE_ALL);
1614 } 1645 }
1615 1646
1616 public byte ConvertScriptUintToByte(uint indata) 1647 public byte ConvertScriptUintToByte(uint indata)
@@ -1679,6 +1710,9 @@ namespace OpenSim.Region.Framework.Scenes
1679 1710
1680 // Move afterwards ResetIDs as it clears the localID 1711 // Move afterwards ResetIDs as it clears the localID
1681 dupe.LocalId = localID; 1712 dupe.LocalId = localID;
1713 if(dupe.PhysActor != null)
1714 dupe.PhysActor.LocalID = localID;
1715
1682 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1716 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1683 dupe._lastOwnerID = OwnerID; 1717 dupe._lastOwnerID = OwnerID;
1684 1718
@@ -1722,7 +1756,7 @@ namespace OpenSim.Region.Framework.Scenes
1722 PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); 1756 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1723 part.Shape = shape; 1757 part.Shape = shape;
1724 1758
1725 part.Name = "Primitive"; 1759 part.Name = "Object";
1726 part._ownerID = UUID.Random(); 1760 part._ownerID = UUID.Random();
1727 1761
1728 return part; 1762 return part;
@@ -2082,12 +2116,17 @@ namespace OpenSim.Region.Framework.Scenes
2082 public Vector3 GetWorldPosition() 2116 public Vector3 GetWorldPosition()
2083 { 2117 {
2084 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2118 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2085
2086 Vector3 axPos = OffsetPosition; 2119 Vector3 axPos = OffsetPosition;
2087
2088 axPos *= parentRot; 2120 axPos *= parentRot;
2089 Vector3 translationOffsetPosition = axPos; 2121 Vector3 translationOffsetPosition = axPos;
2090 return GroupPosition + translationOffsetPosition; 2122 if(_parentID == 0)
2123 {
2124 return GroupPosition;
2125 }
2126 else
2127 {
2128 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2129 }
2091 } 2130 }
2092 2131
2093 /// <summary> 2132 /// <summary>
@@ -2098,7 +2137,7 @@ namespace OpenSim.Region.Framework.Scenes
2098 { 2137 {
2099 Quaternion newRot; 2138 Quaternion newRot;
2100 2139
2101 if (this.LinkNum == 0) 2140 if (this.LinkNum < 2) //KF Single or root prim
2102 { 2141 {
2103 newRot = RotationOffset; 2142 newRot = RotationOffset;
2104 } 2143 }
@@ -2744,17 +2783,18 @@ namespace OpenSim.Region.Framework.Scenes
2744 //Trys to fetch sound id from prim's inventory. 2783 //Trys to fetch sound id from prim's inventory.
2745 //Prim's inventory doesn't support non script items yet 2784 //Prim's inventory doesn't support non script items yet
2746 2785
2747 lock (TaskInventory) 2786 TaskInventory.LockItemsForRead(true);
2787
2788 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2748 { 2789 {
2749 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2790 if (item.Value.Name == sound)
2750 { 2791 {
2751 if (item.Value.Name == sound) 2792 soundID = item.Value.ItemID;
2752 { 2793 break;
2753 soundID = item.Value.ItemID;
2754 break;
2755 }
2756 } 2794 }
2757 } 2795 }
2796
2797 TaskInventory.LockItemsForRead(false);
2758 } 2798 }
2759 2799
2760 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2800 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2814,7 +2854,7 @@ namespace OpenSim.Region.Framework.Scenes
2814 /// <param name="scale"></param> 2854 /// <param name="scale"></param>
2815 public void Resize(Vector3 scale) 2855 public void Resize(Vector3 scale)
2816 { 2856 {
2817 StoreUndoState(); 2857 StoreUndoState(UndoType.STATE_PRIM_SCALE);
2818 m_shape.Scale = scale; 2858 m_shape.Scale = scale;
2819 2859
2820 ParentGroup.HasGroupChanged = true; 2860 ParentGroup.HasGroupChanged = true;
@@ -2823,38 +2863,7 @@ namespace OpenSim.Region.Framework.Scenes
2823 2863
2824 public void RotLookAt(Quaternion target, float strength, float damping) 2864 public void RotLookAt(Quaternion target, float strength, float damping)
2825 { 2865 {
2826 rotLookAt(target, strength, damping); 2866 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2827 }
2828
2829 public void rotLookAt(Quaternion target, float strength, float damping)
2830 {
2831 if (IsAttachment)
2832 {
2833 /*
2834 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2835 if (avatar != null)
2836 {
2837 Rotate the Av?
2838 } */
2839 }
2840 else
2841 {
2842 APIDDamp = damping;
2843 APIDStrength = strength;
2844 APIDTarget = target;
2845 }
2846 }
2847
2848 public void startLookAt(Quaternion rot, float damp, float strength)
2849 {
2850 APIDDamp = damp;
2851 APIDStrength = strength;
2852 APIDTarget = rot;
2853 }
2854
2855 public void stopLookAt()
2856 {
2857 APIDTarget = Quaternion.Identity;
2858 } 2867 }
2859 2868
2860 /// <summary> 2869 /// <summary>
@@ -2866,7 +2875,10 @@ namespace OpenSim.Region.Framework.Scenes
2866 2875
2867 if (m_parentGroup != null) 2876 if (m_parentGroup != null)
2868 { 2877 {
2869 m_parentGroup.QueueForUpdateCheck(); 2878 if (!m_parentGroup.areUpdatesSuspended)
2879 {
2880 m_parentGroup.QueueForUpdateCheck();
2881 }
2870 } 2882 }
2871 2883
2872 int timeNow = Util.UnixTimeSinceEpoch(); 2884 int timeNow = Util.UnixTimeSinceEpoch();
@@ -3083,8 +3095,8 @@ namespace OpenSim.Region.Framework.Scenes
3083 { 3095 {
3084 const float ROTATION_TOLERANCE = 0.01f; 3096 const float ROTATION_TOLERANCE = 0.01f;
3085 const float VELOCITY_TOLERANCE = 0.001f; 3097 const float VELOCITY_TOLERANCE = 0.001f;
3086 const float POSITION_TOLERANCE = 0.05f; 3098 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3087 const int TIME_MS_TOLERANCE = 3000; 3099 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3088 3100
3089 if (m_updateFlag == 1) 3101 if (m_updateFlag == 1)
3090 { 3102 {
@@ -3098,7 +3110,7 @@ namespace OpenSim.Region.Framework.Scenes
3098 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3110 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3099 { 3111 {
3100 AddTerseUpdateToAllAvatars(); 3112 AddTerseUpdateToAllAvatars();
3101 ClearUpdateSchedule(); 3113
3102 3114
3103 // This causes the Scene to 'poll' physical objects every couple of frames 3115 // This causes the Scene to 'poll' physical objects every couple of frames
3104 // bad, so it's been replaced by an event driven method. 3116 // bad, so it's been replaced by an event driven method.
@@ -3116,16 +3128,18 @@ namespace OpenSim.Region.Framework.Scenes
3116 m_lastAngularVelocity = AngularVelocity; 3128 m_lastAngularVelocity = AngularVelocity;
3117 m_lastTerseSent = Environment.TickCount; 3129 m_lastTerseSent = Environment.TickCount;
3118 } 3130 }
3131 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3132 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3119 } 3133 }
3120 else 3134 else
3121 { 3135 {
3122 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3136 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3123 { 3137 {
3124 AddFullUpdateToAllAvatars(); 3138 AddFullUpdateToAllAvatars();
3125 ClearUpdateSchedule(); 3139 m_updateFlag = 0; //Same here
3126 } 3140 }
3127 } 3141 }
3128 ClearUpdateSchedule(); 3142 m_updateFlag = 0;
3129 } 3143 }
3130 3144
3131 /// <summary> 3145 /// <summary>
@@ -3153,17 +3167,16 @@ namespace OpenSim.Region.Framework.Scenes
3153 if (!UUID.TryParse(sound, out soundID)) 3167 if (!UUID.TryParse(sound, out soundID))
3154 { 3168 {
3155 // search sound file from inventory 3169 // search sound file from inventory
3156 lock (TaskInventory) 3170 TaskInventory.LockItemsForRead(true);
3171 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3157 { 3172 {
3158 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3173 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3159 { 3174 {
3160 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3175 soundID = item.Value.ItemID;
3161 { 3176 break;
3162 soundID = item.Value.ItemID;
3163 break;
3164 }
3165 } 3177 }
3166 } 3178 }
3179 TaskInventory.LockItemsForRead(false);
3167 } 3180 }
3168 3181
3169 if (soundID == UUID.Zero) 3182 if (soundID == UUID.Zero)
@@ -3600,7 +3613,7 @@ namespace OpenSim.Region.Framework.Scenes
3600 3613
3601 public void StopLookAt() 3614 public void StopLookAt()
3602 { 3615 {
3603 m_parentGroup.stopLookAt(); 3616 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3604 3617
3605 m_parentGroup.ScheduleGroupForTerseUpdate(); 3618 m_parentGroup.ScheduleGroupForTerseUpdate();
3606 } 3619 }
@@ -3627,10 +3640,9 @@ namespace OpenSim.Region.Framework.Scenes
3627 m_parentGroup.ScheduleGroupForTerseUpdate(); 3640 m_parentGroup.ScheduleGroupForTerseUpdate();
3628 //m_parentGroup.ScheduleGroupForFullUpdate(); 3641 //m_parentGroup.ScheduleGroupForFullUpdate();
3629 } 3642 }
3630 3643 public void StoreUndoState(UndoType type)
3631 public void StoreUndoState()
3632 { 3644 {
3633 if (!Undoing) 3645 if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing))
3634 { 3646 {
3635 if (!IgnoreUndoUpdate) 3647 if (!IgnoreUndoUpdate)
3636 { 3648 {
@@ -3641,17 +3653,25 @@ namespace OpenSim.Region.Framework.Scenes
3641 if (m_undo.Count > 0) 3653 if (m_undo.Count > 0)
3642 { 3654 {
3643 UndoState last = m_undo.Peek(); 3655 UndoState last = m_undo.Peek();
3644 if (last != null) 3656
3645 {
3646 if (last.Compare(this))
3647 return;
3648 }
3649 } 3657 }
3650 3658
3651 if (m_parentGroup.GetSceneMaxUndo() > 0) 3659 if (m_parentGroup.GetSceneMaxUndo() > 0)
3652 { 3660 {
3653 UndoState nUndo = new UndoState(this); 3661 UndoState lastUndo = m_undo.Peek();
3654 3662
3663 UndoState nUndo = new UndoState(this, type);
3664
3665 if (lastUndo != null)
3666 {
3667 TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated);
3668 if (ts.TotalMilliseconds < 500)
3669 {
3670 //Delete the last entry since it was less than 500 milliseconds ago
3671 nUndo.Merge(lastUndo);
3672 m_undo.Pop();
3673 }
3674 }
3655 m_undo.Push(nUndo); 3675 m_undo.Push(nUndo);
3656 } 3676 }
3657 3677
@@ -4128,11 +4148,13 @@ namespace OpenSim.Region.Framework.Scenes
4128 if (m_undo.Count > 0) 4148 if (m_undo.Count > 0)
4129 { 4149 {
4130 UndoState nUndo = null; 4150 UndoState nUndo = null;
4151 UndoState goback = m_undo.Pop();
4131 if (m_parentGroup.GetSceneMaxUndo() > 0) 4152 if (m_parentGroup.GetSceneMaxUndo() > 0)
4132 { 4153 {
4133 nUndo = new UndoState(this); 4154 nUndo = new UndoState(this, goback.Type);
4134 } 4155 }
4135 UndoState goback = m_undo.Pop(); 4156
4157
4136 if (goback != null) 4158 if (goback != null)
4137 { 4159 {
4138 goback.PlaybackState(this); 4160 goback.PlaybackState(this);
@@ -4147,13 +4169,13 @@ namespace OpenSim.Region.Framework.Scenes
4147 { 4169 {
4148 lock (m_redo) 4170 lock (m_redo)
4149 { 4171 {
4172 UndoState gofwd = m_redo.Pop();
4150 if (m_parentGroup.GetSceneMaxUndo() > 0) 4173 if (m_parentGroup.GetSceneMaxUndo() > 0)
4151 { 4174 {
4152 UndoState nUndo = new UndoState(this); 4175 UndoState nUndo = new UndoState(this, gofwd.Type);
4153 4176
4154 m_undo.Push(nUndo); 4177 m_undo.Push(nUndo);
4155 } 4178 }
4156 UndoState gofwd = m_redo.Pop();
4157 if (gofwd != null) 4179 if (gofwd != null)
4158 gofwd.PlayfwdState(this); 4180 gofwd.PlayfwdState(this);
4159 } 4181 }
@@ -4602,8 +4624,9 @@ namespace OpenSim.Region.Framework.Scenes
4602 { 4624 {
4603 m_shape.TextureEntry = textureEntry; 4625 m_shape.TextureEntry = textureEntry;
4604 TriggerScriptChangedEvent(Changed.TEXTURE); 4626 TriggerScriptChangedEvent(Changed.TEXTURE);
4605 4627 m_updateFlag = 1;
4606 ParentGroup.HasGroupChanged = true; 4628 ParentGroup.HasGroupChanged = true;
4629
4607 //This is madness.. 4630 //This is madness..
4608 //ParentGroup.ScheduleGroupForFullUpdate(); 4631 //ParentGroup.ScheduleGroupForFullUpdate();
4609 //This is sparta 4632 //This is sparta
@@ -4836,5 +4859,17 @@ namespace OpenSim.Region.Framework.Scenes
4836 Color color = Color; 4859 Color color = Color;
4837 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4860 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4838 } 4861 }
4862
4863 public void ResetOwnerChangeFlag()
4864 {
4865 List<UUID> inv = Inventory.GetInventoryList();
4866
4867 foreach (UUID itemID in inv)
4868 {
4869 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4870 item.OwnerChanged = false;
4871 Inventory.UpdateInventoryItem(item, false, false);
4872 }
4873 }
4839 } 4874 }
4840} 4875}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 6a204c3..8fcfcc5 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -47,6 +47,8 @@ namespace OpenSim.Region.Framework.Scenes
47 47
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private int m_inventoryFileNameSerial = 0; 49 private int m_inventoryFileNameSerial = 0;
50
51 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
50 52
51 /// <value> 53 /// <value>
52 /// The part to which the inventory belongs. 54 /// The part to which the inventory belongs.
@@ -83,7 +85,9 @@ namespace OpenSim.Region.Framework.Scenes
83 /// </value> 85 /// </value>
84 protected internal TaskInventoryDictionary Items 86 protected internal TaskInventoryDictionary Items
85 { 87 {
86 get { return m_items; } 88 get {
89 return m_items;
90 }
87 set 91 set
88 { 92 {
89 m_items = value; 93 m_items = value;
@@ -119,39 +123,45 @@ namespace OpenSim.Region.Framework.Scenes
119 /// <param name="linkNum">Link number for the part</param> 123 /// <param name="linkNum">Link number for the part</param>
120 public void ResetInventoryIDs() 124 public void ResetInventoryIDs()
121 { 125 {
122 if (null == m_part || null == m_part.ParentGroup) 126 m_items.LockItemsForWrite(true);
123 return; 127
124 128 if (Items.Count == 0)
125 lock (m_items)
126 { 129 {
127 if (0 == m_items.Count) 130 m_items.LockItemsForWrite(false);
128 return; 131 return;
132 }
129 133
130 IList<TaskInventoryItem> items = GetInventoryItems(); 134 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
131 m_items.Clear(); 135 Items.Clear();
132 136
133 foreach (TaskInventoryItem item in items) 137 foreach (TaskInventoryItem item in items)
134 { 138 {
135 item.ResetIDs(m_part.UUID); 139 item.ResetIDs(m_part.UUID);
136 m_items.Add(item.ItemID, item); 140 Items.Add(item.ItemID, item);
137 }
138 } 141 }
142 m_items.LockItemsForWrite(false);
139 } 143 }
140 144
141 public void ResetObjectID() 145 public void ResetObjectID()
142 { 146 {
143 lock (Items) 147 m_items.LockItemsForWrite(true);
148
149 if (Items.Count == 0)
144 { 150 {
145 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 151 m_items.LockItemsForWrite(false);
146 Items.Clear(); 152 return;
147
148 foreach (TaskInventoryItem item in items)
149 {
150 item.ParentPartID = m_part.UUID;
151 item.ParentID = m_part.UUID;
152 Items.Add(item.ItemID, item);
153 }
154 } 153 }
154
155 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
156 Items.Clear();
157
158 foreach (TaskInventoryItem item in items)
159 {
160 item.ParentPartID = m_part.UUID;
161 item.ParentID = m_part.UUID;
162 Items.Add(item.ItemID, item);
163 }
164 m_items.LockItemsForWrite(false);
155 } 165 }
156 166
157 /// <summary> 167 /// <summary>
@@ -160,12 +170,11 @@ namespace OpenSim.Region.Framework.Scenes
160 /// <param name="ownerId"></param> 170 /// <param name="ownerId"></param>
161 public void ChangeInventoryOwner(UUID ownerId) 171 public void ChangeInventoryOwner(UUID ownerId)
162 { 172 {
163 lock (Items) 173 m_items.LockItemsForWrite(true);
174 if (0 == Items.Count)
164 { 175 {
165 if (0 == Items.Count) 176 m_items.LockItemsForWrite(false);
166 { 177 return;
167 return;
168 }
169 } 178 }
170 179
171 HasInventoryChanged = true; 180 HasInventoryChanged = true;
@@ -179,6 +188,7 @@ namespace OpenSim.Region.Framework.Scenes
179 item.OwnerID = ownerId; 188 item.OwnerID = ownerId;
180 } 189 }
181 } 190 }
191 m_items.LockItemsForWrite(false);
182 } 192 }
183 193
184 /// <summary> 194 /// <summary>
@@ -187,12 +197,11 @@ namespace OpenSim.Region.Framework.Scenes
187 /// <param name="groupID"></param> 197 /// <param name="groupID"></param>
188 public void ChangeInventoryGroup(UUID groupID) 198 public void ChangeInventoryGroup(UUID groupID)
189 { 199 {
190 lock (Items) 200 m_items.LockItemsForWrite(true);
201 if (0 == Items.Count)
191 { 202 {
192 if (0 == Items.Count) 203 m_items.LockItemsForWrite(false);
193 { 204 return;
194 return;
195 }
196 } 205 }
197 206
198 // Don't let this set the HasGroupChanged flag for attachments 207 // Don't let this set the HasGroupChanged flag for attachments
@@ -204,12 +213,15 @@ namespace OpenSim.Region.Framework.Scenes
204 m_part.ParentGroup.HasGroupChanged = true; 213 m_part.ParentGroup.HasGroupChanged = true;
205 } 214 }
206 215
207 List<TaskInventoryItem> items = GetInventoryItems(); 216 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
208 foreach (TaskInventoryItem item in items) 217 foreach (TaskInventoryItem item in items)
209 { 218 {
210 if (groupID != item.GroupID) 219 if (groupID != item.GroupID)
220 {
211 item.GroupID = groupID; 221 item.GroupID = groupID;
222 }
212 } 223 }
224 m_items.LockItemsForWrite(false);
213 } 225 }
214 226
215 /// <summary> 227 /// <summary>
@@ -217,9 +229,14 @@ namespace OpenSim.Region.Framework.Scenes
217 /// </summary> 229 /// </summary>
218 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 230 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
219 { 231 {
220 List<TaskInventoryItem> scripts = GetInventoryScripts(); 232 Items.LockItemsForRead(true);
221 foreach (TaskInventoryItem item in scripts) 233 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
222 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 234 Items.LockItemsForRead(false);
235 foreach (TaskInventoryItem item in items)
236 {
237 if ((int)InventoryType.LSL == item.InvType)
238 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
239 }
223 } 240 }
224 241
225 public ArrayList GetScriptErrors(UUID itemID) 242 public ArrayList GetScriptErrors(UUID itemID)
@@ -252,9 +269,18 @@ namespace OpenSim.Region.Framework.Scenes
252 /// </param> 269 /// </param>
253 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 270 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
254 { 271 {
255 List<TaskInventoryItem> scripts = GetInventoryScripts(); 272 Items.LockItemsForRead(true);
256 foreach (TaskInventoryItem item in scripts) 273 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
257 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 274 Items.LockItemsForRead(false);
275
276 foreach (TaskInventoryItem item in items)
277 {
278 if ((int)InventoryType.LSL == item.InvType)
279 {
280 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
281 m_part.RemoveScriptEvents(item.ItemID);
282 }
283 }
258 } 284 }
259 285
260 /// <summary> 286 /// <summary>
@@ -270,7 +296,10 @@ namespace OpenSim.Region.Framework.Scenes
270 // item.Name, item.ItemID, Name, UUID); 296 // item.Name, item.ItemID, Name, UUID);
271 297
272 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 298 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
299 {
300 StoreScriptError(item.ItemID, "no permission");
273 return; 301 return;
302 }
274 303
275 m_part.AddFlag(PrimFlags.Scripted); 304 m_part.AddFlag(PrimFlags.Scripted);
276 305
@@ -279,14 +308,13 @@ namespace OpenSim.Region.Framework.Scenes
279 if (stateSource == 2 && // Prim crossing 308 if (stateSource == 2 && // Prim crossing
280 m_part.ParentGroup.Scene.m_trustBinaries) 309 m_part.ParentGroup.Scene.m_trustBinaries)
281 { 310 {
282 lock (m_items) 311 m_items.LockItemsForWrite(true);
283 { 312 m_items[item.ItemID].PermsMask = 0;
284 m_items[item.ItemID].PermsMask = 0; 313 m_items[item.ItemID].PermsGranter = UUID.Zero;
285 m_items[item.ItemID].PermsGranter = UUID.Zero; 314 m_items.LockItemsForWrite(false);
286 }
287
288 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 315 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
289 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 316 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
317 StoreScriptErrors(item.ItemID, null);
290 m_part.ParentGroup.AddActiveScriptCount(1); 318 m_part.ParentGroup.AddActiveScriptCount(1);
291 m_part.ScheduleFullUpdate(); 319 m_part.ScheduleFullUpdate();
292 return; 320 return;
@@ -295,6 +323,8 @@ namespace OpenSim.Region.Framework.Scenes
295 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 323 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
296 if (null == asset) 324 if (null == asset)
297 { 325 {
326 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
327 StoreScriptError(item.ItemID, msg);
298 m_log.ErrorFormat( 328 m_log.ErrorFormat(
299 "[PRIM INVENTORY]: " + 329 "[PRIM INVENTORY]: " +
300 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 330 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -306,15 +336,17 @@ namespace OpenSim.Region.Framework.Scenes
306 if (m_part.ParentGroup.m_savedScriptState != null) 336 if (m_part.ParentGroup.m_savedScriptState != null)
307 RestoreSavedScriptState(item.OldItemID, item.ItemID); 337 RestoreSavedScriptState(item.OldItemID, item.ItemID);
308 338
309 lock (m_items) 339 m_items.LockItemsForWrite(true);
310 { 340
311 m_items[item.ItemID].PermsMask = 0; 341 m_items[item.ItemID].PermsMask = 0;
312 m_items[item.ItemID].PermsGranter = UUID.Zero; 342 m_items[item.ItemID].PermsGranter = UUID.Zero;
313 } 343
344 m_items.LockItemsForWrite(false);
314 345
315 string script = Utils.BytesToString(asset.Data); 346 string script = Utils.BytesToString(asset.Data);
316 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 347 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
317 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 348 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
349 StoreScriptErrors(item.ItemID, null);
318 m_part.ParentGroup.AddActiveScriptCount(1); 350 m_part.ParentGroup.AddActiveScriptCount(1);
319 m_part.ScheduleFullUpdate(); 351 m_part.ScheduleFullUpdate();
320 } 352 }
@@ -378,21 +410,145 @@ namespace OpenSim.Region.Framework.Scenes
378 410
379 /// <summary> 411 /// <summary>
380 /// Start a script which is in this prim's inventory. 412 /// Start a script which is in this prim's inventory.
413 /// Some processing may occur in the background, but this routine returns asap.
381 /// </summary> 414 /// </summary>
382 /// <param name="itemId"> 415 /// <param name="itemId">
383 /// A <see cref="UUID"/> 416 /// A <see cref="UUID"/>
384 /// </param> 417 /// </param>
385 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 418 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
386 { 419 {
387 TaskInventoryItem item = GetInventoryItem(itemId); 420 lock (m_scriptErrors)
388 if (item != null) 421 {
389 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 422 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
423 m_scriptErrors.Remove(itemId);
424 }
425 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
426 }
427
428 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
429 {
430 m_items.LockItemsForRead(true);
431 if (m_items.ContainsKey(itemId))
432 {
433 if (m_items.ContainsKey(itemId))
434 {
435 m_items.LockItemsForRead(false);
436 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
437 }
438 else
439 {
440 m_items.LockItemsForRead(false);
441 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
442 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
443 StoreScriptError(itemId, msg);
444 m_log.ErrorFormat(
445 "[PRIM INVENTORY]: " +
446 "Couldn't start script with ID {0} since it {1}", itemId, msg);
447 }
448 }
390 else 449 else
450 {
451 m_items.LockItemsForRead(false);
452 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
453 StoreScriptError(itemId, msg);
391 m_log.ErrorFormat( 454 m_log.ErrorFormat(
392 "[PRIM INVENTORY]: " + 455 "[PRIM INVENTORY]: " +
393 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 456 "Couldn't start script with ID {0} since it {1}", itemId, msg);
394 itemId, m_part.Name, m_part.UUID, 457 }
395 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 458
459 }
460
461 /// <summary>
462 /// Start a script which is in this prim's inventory and return any compilation error messages.
463 /// </summary>
464 /// <param name="itemId">
465 /// A <see cref="UUID"/>
466 /// </param>
467 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
468 {
469 ArrayList errors;
470
471 // Indicate to CreateScriptInstanceInternal() we want it to
472 // post any compilation/loading error messages
473 lock (m_scriptErrors)
474 {
475 m_scriptErrors[itemId] = null;
476 }
477
478 // Perform compilation/loading
479 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
480
481 // Wait for and retrieve any errors
482 lock (m_scriptErrors)
483 {
484 while ((errors = m_scriptErrors[itemId]) == null)
485 {
486 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
487 {
488 m_log.ErrorFormat(
489 "[PRIM INVENTORY]: " +
490 "timedout waiting for script {0} errors", itemId);
491 errors = m_scriptErrors[itemId];
492 if (errors == null)
493 {
494 errors = new ArrayList(1);
495 errors.Add("timedout waiting for errors");
496 }
497 break;
498 }
499 }
500 m_scriptErrors.Remove(itemId);
501 }
502 return errors;
503 }
504
505 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
506 private void StoreScriptErrors(UUID itemId, ArrayList errors)
507 {
508 lock (m_scriptErrors)
509 {
510 // If compilation/loading initiated via CreateScriptInstance(),
511 // it does not want the errors, so just get out
512 if (!m_scriptErrors.ContainsKey(itemId))
513 {
514 return;
515 }
516
517 // Initiated via CreateScriptInstanceEr(), if we know what the
518 // errors are, save them and wake CreateScriptInstanceEr().
519 if (errors != null)
520 {
521 m_scriptErrors[itemId] = errors;
522 System.Threading.Monitor.PulseAll(m_scriptErrors);
523 return;
524 }
525 }
526
527 // Initiated via CreateScriptInstanceEr() but we don't know what
528 // the errors are yet, so retrieve them from the script engine.
529 // This may involve some waiting internal to GetScriptErrors().
530 errors = GetScriptErrors(itemId);
531
532 // Get a default non-null value to indicate success.
533 if (errors == null)
534 {
535 errors = new ArrayList();
536 }
537
538 // Post to CreateScriptInstanceEr() and wake it up
539 lock (m_scriptErrors)
540 {
541 m_scriptErrors[itemId] = errors;
542 System.Threading.Monitor.PulseAll(m_scriptErrors);
543 }
544 }
545
546 // Like StoreScriptErrors(), but just posts a single string message
547 private void StoreScriptError(UUID itemId, string message)
548 {
549 ArrayList errors = new ArrayList(1);
550 errors.Add(message);
551 StoreScriptErrors(itemId, errors);
396 } 552 }
397 553
398 /// <summary> 554 /// <summary>
@@ -405,15 +561,7 @@ namespace OpenSim.Region.Framework.Scenes
405 /// </param> 561 /// </param>
406 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 562 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
407 { 563 {
408 bool scriptPresent = false; 564 if (m_items.ContainsKey(itemId))
409
410 lock (m_items)
411 {
412 if (m_items.ContainsKey(itemId))
413 scriptPresent = true;
414 }
415
416 if (scriptPresent)
417 { 565 {
418 if (!sceneObjectBeingDeleted) 566 if (!sceneObjectBeingDeleted)
419 m_part.RemoveScriptEvents(itemId); 567 m_part.RemoveScriptEvents(itemId);
@@ -438,14 +586,16 @@ namespace OpenSim.Region.Framework.Scenes
438 /// <returns></returns> 586 /// <returns></returns>
439 private bool InventoryContainsName(string name) 587 private bool InventoryContainsName(string name)
440 { 588 {
441 lock (m_items) 589 m_items.LockItemsForRead(true);
590 foreach (TaskInventoryItem item in m_items.Values)
442 { 591 {
443 foreach (TaskInventoryItem item in m_items.Values) 592 if (item.Name == name)
444 { 593 {
445 if (item.Name == name) 594 m_items.LockItemsForRead(false);
446 return true; 595 return true;
447 } 596 }
448 } 597 }
598 m_items.LockItemsForRead(false);
449 return false; 599 return false;
450 } 600 }
451 601
@@ -487,8 +637,9 @@ namespace OpenSim.Region.Framework.Scenes
487 /// <param name="item"></param> 637 /// <param name="item"></param>
488 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 638 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
489 { 639 {
490 List<TaskInventoryItem> il = GetInventoryItems(); 640 m_items.LockItemsForRead(true);
491 641 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
642 m_items.LockItemsForRead(false);
492 foreach (TaskInventoryItem i in il) 643 foreach (TaskInventoryItem i in il)
493 { 644 {
494 if (i.Name == item.Name) 645 if (i.Name == item.Name)
@@ -526,14 +677,14 @@ namespace OpenSim.Region.Framework.Scenes
526 item.Name = name; 677 item.Name = name;
527 item.GroupID = m_part.GroupID; 678 item.GroupID = m_part.GroupID;
528 679
529 lock (m_items) 680 m_items.LockItemsForWrite(true);
530 m_items.Add(item.ItemID, item); 681 m_items.Add(item.ItemID, item);
531 682 m_items.LockItemsForWrite(false);
532 if (allowedDrop) 683 if (allowedDrop)
533 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 684 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
534 else 685 else
535 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 686 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
536 687
537 m_inventorySerial++; 688 m_inventorySerial++;
538 //m_inventorySerial += 2; 689 //m_inventorySerial += 2;
539 HasInventoryChanged = true; 690 HasInventoryChanged = true;
@@ -549,15 +700,15 @@ namespace OpenSim.Region.Framework.Scenes
549 /// <param name="items"></param> 700 /// <param name="items"></param>
550 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 701 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
551 { 702 {
552 lock (m_items) 703 m_items.LockItemsForWrite(true);
704 foreach (TaskInventoryItem item in items)
553 { 705 {
554 foreach (TaskInventoryItem item in items) 706 m_items.Add(item.ItemID, item);
555 { 707// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
556 m_items.Add(item.ItemID, item);
557// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
558 }
559 m_inventorySerial++;
560 } 708 }
709 m_items.LockItemsForWrite(false);
710
711 m_inventorySerial++;
561 } 712 }
562 713
563 /// <summary> 714 /// <summary>
@@ -568,10 +719,9 @@ namespace OpenSim.Region.Framework.Scenes
568 public TaskInventoryItem GetInventoryItem(UUID itemId) 719 public TaskInventoryItem GetInventoryItem(UUID itemId)
569 { 720 {
570 TaskInventoryItem item; 721 TaskInventoryItem item;
571 722 m_items.LockItemsForRead(true);
572 lock (m_items) 723 m_items.TryGetValue(itemId, out item);
573 m_items.TryGetValue(itemId, out item); 724 m_items.LockItemsForRead(false);
574
575 return item; 725 return item;
576 } 726 }
577 727
@@ -587,15 +737,16 @@ namespace OpenSim.Region.Framework.Scenes
587 { 737 {
588 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 738 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
589 739
590 lock (m_items) 740 m_items.LockItemsForRead(true);
741
742 foreach (TaskInventoryItem item in m_items.Values)
591 { 743 {
592 foreach (TaskInventoryItem item in m_items.Values) 744 if (item.Name == name)
593 { 745 items.Add(item);
594 if (item.Name == name)
595 items.Add(item);
596 }
597 } 746 }
598 747
748 m_items.LockItemsForRead(false);
749
599 return items; 750 return items;
600 } 751 }
601 752
@@ -678,9 +829,9 @@ namespace OpenSim.Region.Framework.Scenes
678 829
679 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 830 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
680 { 831 {
681 TaskInventoryItem it = GetInventoryItem(item.ItemID); 832 m_items.LockItemsForWrite(true);
682 if (it != null)
683 833
834 if (m_items.ContainsKey(item.ItemID))
684 { 835 {
685 item.ParentID = m_part.UUID; 836 item.ParentID = m_part.UUID;
686 item.ParentPartID = m_part.UUID; 837 item.ParentPartID = m_part.UUID;
@@ -692,14 +843,10 @@ namespace OpenSim.Region.Framework.Scenes
692 item.GroupID = m_part.GroupID; 843 item.GroupID = m_part.GroupID;
693 844
694 if (item.AssetID == UUID.Zero) 845 if (item.AssetID == UUID.Zero)
695 item.AssetID = it.AssetID; 846 item.AssetID = m_items[item.ItemID].AssetID;
696
697 lock (m_items)
698 {
699 m_items[item.ItemID] = item;
700 m_inventorySerial++;
701 }
702 847
848 m_items[item.ItemID] = item;
849 m_inventorySerial++;
703 if (fireScriptEvents) 850 if (fireScriptEvents)
704 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 851 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
705 if (considerChanged) 852 if (considerChanged)
@@ -707,6 +854,7 @@ namespace OpenSim.Region.Framework.Scenes
707 HasInventoryChanged = true; 854 HasInventoryChanged = true;
708 m_part.ParentGroup.HasGroupChanged = true; 855 m_part.ParentGroup.HasGroupChanged = true;
709 } 856 }
857 m_items.LockItemsForWrite(false);
710 return true; 858 return true;
711 } 859 }
712 else 860 else
@@ -717,8 +865,9 @@ namespace OpenSim.Region.Framework.Scenes
717 item.ItemID, m_part.Name, m_part.UUID, 865 item.ItemID, m_part.Name, m_part.UUID,
718 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 866 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
719 } 867 }
720 return false; 868 m_items.LockItemsForWrite(false);
721 869
870 return false;
722 } 871 }
723 872
724 /// <summary> 873 /// <summary>
@@ -729,37 +878,53 @@ namespace OpenSim.Region.Framework.Scenes
729 /// in this prim's inventory.</returns> 878 /// in this prim's inventory.</returns>
730 public int RemoveInventoryItem(UUID itemID) 879 public int RemoveInventoryItem(UUID itemID)
731 { 880 {
732 TaskInventoryItem item = GetInventoryItem(itemID); 881 m_items.LockItemsForRead(true);
733 if (item != null) 882
883 if (m_items.ContainsKey(itemID))
734 { 884 {
735 int type = m_items[itemID].InvType; 885 int type = m_items[itemID].InvType;
886 m_items.LockItemsForRead(false);
736 if (type == 10) // Script 887 if (type == 10) // Script
737 { 888 {
738 m_part.RemoveScriptEvents(itemID);
739 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 889 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
740 } 890 }
891 m_items.LockItemsForWrite(true);
741 m_items.Remove(itemID); 892 m_items.Remove(itemID);
893 m_items.LockItemsForWrite(false);
742 m_inventorySerial++; 894 m_inventorySerial++;
743 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 895 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
744 896
745 HasInventoryChanged = true; 897 HasInventoryChanged = true;
746 m_part.ParentGroup.HasGroupChanged = true; 898 m_part.ParentGroup.HasGroupChanged = true;
747 899
748 if (!ContainsScripts()) 900 int scriptcount = 0;
901 m_items.LockItemsForRead(true);
902 foreach (TaskInventoryItem item in m_items.Values)
903 {
904 if (item.Type == 10)
905 {
906 scriptcount++;
907 }
908 }
909 m_items.LockItemsForRead(false);
910
911
912 if (scriptcount <= 0)
913 {
749 m_part.RemFlag(PrimFlags.Scripted); 914 m_part.RemFlag(PrimFlags.Scripted);
915 }
750 916
751 m_part.ScheduleFullUpdate(); 917 m_part.ScheduleFullUpdate();
752 918
753 return type; 919 return type;
754
755 } 920 }
756 else 921 else
757 { 922 {
923 m_items.LockItemsForRead(false);
758 m_log.ErrorFormat( 924 m_log.ErrorFormat(
759 "[PRIM INVENTORY]: " + 925 "[PRIM INVENTORY]: " +
760 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 926 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
761 itemID, m_part.Name, m_part.UUID, 927 itemID, m_part.Name, m_part.UUID);
762 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
763 } 928 }
764 929
765 return -1; 930 return -1;
@@ -867,6 +1032,8 @@ namespace OpenSim.Region.Framework.Scenes
867 invString.AddSectionEnd(); 1032 invString.AddSectionEnd();
868 } 1033 }
869 } 1034 }
1035 int count = m_items.Count;
1036 m_items.LockItemsForRead(false);
870 1037
871 fileData = Utils.StringToBytes(invString.BuildString); 1038 fileData = Utils.StringToBytes(invString.BuildString);
872 1039
@@ -887,10 +1054,11 @@ namespace OpenSim.Region.Framework.Scenes
887 { 1054 {
888 if (HasInventoryChanged) 1055 if (HasInventoryChanged)
889 { 1056 {
890 HasInventoryChanged = false; 1057 Items.LockItemsForRead(true);
891 List<TaskInventoryItem> items = GetInventoryItems(); 1058 datastore.StorePrimInventory(m_part.UUID, Items.Values);
892 datastore.StorePrimInventory(m_part.UUID, items); 1059 Items.LockItemsForRead(false);
893 1060
1061 HasInventoryChanged = false;
894 } 1062 }
895 } 1063 }
896 1064
@@ -957,89 +1125,75 @@ namespace OpenSim.Region.Framework.Scenes
957 { 1125 {
958 uint mask=0x7fffffff; 1126 uint mask=0x7fffffff;
959 1127
960 lock (m_items) 1128 foreach (TaskInventoryItem item in m_items.Values)
961 { 1129 {
962 foreach (TaskInventoryItem item in m_items.Values) 1130 if (item.InvType != (int)InventoryType.Object)
963 { 1131 {
964 if (item.InvType != (int)InventoryType.Object) 1132 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
965 { 1133 mask &= ~((uint)PermissionMask.Copy >> 13);
966 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1134 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
967 mask &= ~((uint)PermissionMask.Copy >> 13); 1135 mask &= ~((uint)PermissionMask.Transfer >> 13);
968 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1136 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
969 mask &= ~((uint)PermissionMask.Transfer >> 13); 1137 mask &= ~((uint)PermissionMask.Modify >> 13);
970 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1138 }
971 mask &= ~((uint)PermissionMask.Modify >> 13); 1139 else
972 } 1140 {
973 else 1141 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
974 { 1142 mask &= ~((uint)PermissionMask.Copy >> 13);
975 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1143 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
976 mask &= ~((uint)PermissionMask.Copy >> 13); 1144 mask &= ~((uint)PermissionMask.Transfer >> 13);
977 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1145 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
978 mask &= ~((uint)PermissionMask.Transfer >> 13); 1146 mask &= ~((uint)PermissionMask.Modify >> 13);
979 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
980 mask &= ~((uint)PermissionMask.Modify >> 13);
981 }
982
983 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
984 mask &= ~(uint)PermissionMask.Copy;
985 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
986 mask &= ~(uint)PermissionMask.Transfer;
987 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
988 mask &= ~(uint)PermissionMask.Modify;
989 } 1147 }
1148
1149 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1150 mask &= ~(uint)PermissionMask.Copy;
1151 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1152 mask &= ~(uint)PermissionMask.Transfer;
1153 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1154 mask &= ~(uint)PermissionMask.Modify;
990 } 1155 }
991
992 return mask; 1156 return mask;
993 } 1157 }
994 1158
995 public void ApplyNextOwnerPermissions() 1159 public void ApplyNextOwnerPermissions()
996 { 1160 {
997 lock (m_items) 1161 foreach (TaskInventoryItem item in m_items.Values)
998 { 1162 {
999 foreach (TaskInventoryItem item in m_items.Values) 1163 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1000 { 1164 {
1001 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1165 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1002 { 1166 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1003 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1167 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1004 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1168 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1005 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1169 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1006 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1170 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1007 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1008 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1009 }
1010 item.CurrentPermissions &= item.NextPermissions;
1011 item.BasePermissions &= item.NextPermissions;
1012 item.EveryonePermissions &= item.NextPermissions;
1013 item.OwnerChanged = true;
1014 } 1171 }
1172 item.OwnerChanged = true;
1173 item.CurrentPermissions &= item.NextPermissions;
1174 item.BasePermissions &= item.NextPermissions;
1175 item.EveryonePermissions &= item.NextPermissions;
1015 } 1176 }
1016 } 1177 }
1017 1178
1018 public void ApplyGodPermissions(uint perms) 1179 public void ApplyGodPermissions(uint perms)
1019 { 1180 {
1020 lock (m_items) 1181 foreach (TaskInventoryItem item in m_items.Values)
1021 { 1182 {
1022 foreach (TaskInventoryItem item in m_items.Values) 1183 item.CurrentPermissions = perms;
1023 { 1184 item.BasePermissions = perms;
1024 item.CurrentPermissions = perms;
1025 item.BasePermissions = perms;
1026 }
1027 } 1185 }
1028 } 1186 }
1029 1187
1030 public bool ContainsScripts() 1188 public bool ContainsScripts()
1031 { 1189 {
1032 lock (m_items) 1190 foreach (TaskInventoryItem item in m_items.Values)
1033 { 1191 {
1034 foreach (TaskInventoryItem item in m_items.Values) 1192 if (item.InvType == (int)InventoryType.LSL)
1035 { 1193 {
1036 if (item.InvType == (int)InventoryType.LSL) 1194 return true;
1037 {
1038 return true;
1039 }
1040 } 1195 }
1041 } 1196 }
1042
1043 return false; 1197 return false;
1044 } 1198 }
1045 1199
@@ -1047,11 +1201,8 @@ namespace OpenSim.Region.Framework.Scenes
1047 { 1201 {
1048 List<UUID> ret = new List<UUID>(); 1202 List<UUID> ret = new List<UUID>();
1049 1203
1050 lock (m_items) 1204 foreach (TaskInventoryItem item in m_items.Values)
1051 { 1205 ret.Add(item.ItemID);
1052 foreach (TaskInventoryItem item in m_items.Values)
1053 ret.Add(item.ItemID);
1054 }
1055 1206
1056 return ret; 1207 return ret;
1057 } 1208 }
@@ -1082,31 +1233,46 @@ namespace OpenSim.Region.Framework.Scenes
1082 1233
1083 public Dictionary<UUID, string> GetScriptStates() 1234 public Dictionary<UUID, string> GetScriptStates()
1084 { 1235 {
1236 return GetScriptStates(false);
1237 }
1238
1239 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1240 {
1085 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1241 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1086 1242
1087 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1243 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1088 if (engines == null) // No engine at all 1244 if (engines == null) // No engine at all
1089 return ret; 1245 return ret;
1090 1246
1091 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1247 Items.LockItemsForRead(true);
1092 1248 foreach (TaskInventoryItem item in m_items.Values)
1093 foreach (TaskInventoryItem item in scripts)
1094 { 1249 {
1095 foreach (IScriptModule e in engines) 1250 if (item.InvType == (int)InventoryType.LSL)
1096 { 1251 {
1097 if (e != null) 1252 foreach (IScriptModule e in engines)
1098 { 1253 {
1099 string n = e.GetXMLState(item.ItemID); 1254 if (e != null)
1100 if (n != String.Empty)
1101 { 1255 {
1102 if (!ret.ContainsKey(item.ItemID)) 1256 string n = e.GetXMLState(item.ItemID);
1103 ret[item.ItemID] = n; 1257 if (n != String.Empty)
1104 break; 1258 {
1259 if (oldIDs)
1260 {
1261 if (!ret.ContainsKey(item.OldItemID))
1262 ret[item.OldItemID] = n;
1263 }
1264 else
1265 {
1266 if (!ret.ContainsKey(item.ItemID))
1267 ret[item.ItemID] = n;
1268 }
1269 break;
1270 }
1105 } 1271 }
1106 } 1272 }
1107 } 1273 }
1108 } 1274 }
1109 1275 Items.LockItemsForRead(false);
1110 return ret; 1276 return ret;
1111 } 1277 }
1112 1278
@@ -1116,21 +1282,27 @@ namespace OpenSim.Region.Framework.Scenes
1116 if (engines == null) 1282 if (engines == null)
1117 return; 1283 return;
1118 1284
1119 List<TaskInventoryItem> scripts = GetInventoryScripts();
1120 1285
1121 foreach (TaskInventoryItem item in scripts) 1286 Items.LockItemsForRead(true);
1287
1288 foreach (TaskInventoryItem item in m_items.Values)
1122 { 1289 {
1123 foreach (IScriptModule engine in engines) 1290 if (item.InvType == (int)InventoryType.LSL)
1124 { 1291 {
1125 if (engine != null) 1292 foreach (IScriptModule engine in engines)
1126 { 1293 {
1127 if (item.OwnerChanged) 1294 if (engine != null)
1128 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1295 {
1129 item.OwnerChanged = false; 1296 if (item.OwnerChanged)
1130 engine.ResumeScript(item.ItemID); 1297 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1298 item.OwnerChanged = false;
1299 engine.ResumeScript(item.ItemID);
1300 }
1131 } 1301 }
1132 } 1302 }
1133 } 1303 }
1304
1305 Items.LockItemsForRead(false);
1134 } 1306 }
1135 } 1307 }
1136} 1308}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a1c80e5..7ce94d4 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.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 System.Reflection; 31using System.Reflection;
31using System.Timers; 32using System.Timers;
@@ -72,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes
72// { 73// {
73// m_log.Debug("[ScenePresence] Destructor called"); 74// m_log.Debug("[ScenePresence] Destructor called");
74// } 75// }
75 76
76 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
77 78
78// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 79// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
@@ -87,7 +88,9 @@ namespace OpenSim.Region.Framework.Scenes
87 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 88 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
88 /// issue #1716 89 /// issue #1716
89 /// </summary> 90 /// </summary>
90 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 91// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
92 // Value revised by KF 091121 by comparison with SL.
93 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
91 94
92 public UUID currentParcelUUID = UUID.Zero; 95 public UUID currentParcelUUID = UUID.Zero;
93 96
@@ -121,8 +124,11 @@ namespace OpenSim.Region.Framework.Scenes
121 public Vector3 lastKnownAllowedPosition; 124 public Vector3 lastKnownAllowedPosition;
122 public bool sentMessageAboutRestrictedParcelFlyingDown; 125 public bool sentMessageAboutRestrictedParcelFlyingDown;
123 public Vector4 CollisionPlane = Vector4.UnitW; 126 public Vector4 CollisionPlane = Vector4.UnitW;
124 127
128 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
129 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
125 private Vector3 m_lastPosition; 130 private Vector3 m_lastPosition;
131 private Vector3 m_lastWorldPosition;
126 private Quaternion m_lastRotation; 132 private Quaternion m_lastRotation;
127 private Vector3 m_lastVelocity; 133 private Vector3 m_lastVelocity;
128 //private int m_lastTerseSent; 134 //private int m_lastTerseSent;
@@ -153,9 +159,10 @@ namespace OpenSim.Region.Framework.Scenes
153 private int m_perfMonMS; 159 private int m_perfMonMS;
154 160
155 private bool m_setAlwaysRun; 161 private bool m_setAlwaysRun;
156
157 private bool m_forceFly; 162 private bool m_forceFly;
158 private bool m_flyDisabled; 163 private bool m_flyDisabled;
164 private bool m_flyingOld; // add for fly velocity control
165 public bool m_wasFlying; // add for fly velocity control
159 166
160 private float m_speedModifier = 1.0f; 167 private float m_speedModifier = 1.0f;
161 168
@@ -174,7 +181,8 @@ namespace OpenSim.Region.Framework.Scenes
174 protected RegionInfo m_regionInfo; 181 protected RegionInfo m_regionInfo;
175 protected ulong crossingFromRegion; 182 protected ulong crossingFromRegion;
176 183
177 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 184 private readonly Vector3[] Dir_Vectors = new Vector3[11];
185 private bool m_isNudging = false;
178 186
179 // Position of agent's camera in world (region cordinates) 187 // Position of agent's camera in world (region cordinates)
180 protected Vector3 m_CameraCenter; 188 protected Vector3 m_CameraCenter;
@@ -199,17 +207,25 @@ namespace OpenSim.Region.Framework.Scenes
199 private bool m_autopilotMoving; 207 private bool m_autopilotMoving;
200 private Vector3 m_autoPilotTarget; 208 private Vector3 m_autoPilotTarget;
201 private bool m_sitAtAutoTarget; 209 private bool m_sitAtAutoTarget;
210 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
202 211
203 private string m_nextSitAnimation = String.Empty; 212 private string m_nextSitAnimation = String.Empty;
204 213
205 //PauPaw:Proper PID Controler for autopilot************ 214 //PauPaw:Proper PID Controler for autopilot************
206 private bool m_moveToPositionInProgress; 215 private bool m_moveToPositionInProgress;
207 private Vector3 m_moveToPositionTarget; 216 private Vector3 m_moveToPositionTarget;
217 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
208 218
209 private bool m_followCamAuto; 219 private bool m_followCamAuto;
210 220
211 private int m_movementUpdateCount; 221 private int m_movementUpdateCount;
222 private int m_lastColCount = -1; //KF: Look for Collision chnages
223 private int m_updateCount = 0; //KF: Update Anims for a while
224 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
212 private const int NumMovementsBetweenRayCast = 5; 225 private const int NumMovementsBetweenRayCast = 5;
226 private List<uint> m_lastColliders = new List<uint>();
227
228 private object m_syncRoot = new Object();
213 229
214 private bool CameraConstraintActive; 230 private bool CameraConstraintActive;
215 //private int m_moveToPositionStateStatus; 231 //private int m_moveToPositionStateStatus;
@@ -236,7 +252,9 @@ namespace OpenSim.Region.Framework.Scenes
236 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 252 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
237 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 253 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
238 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 254 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
239 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 255 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
256 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
257 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
240 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 258 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
241 } 259 }
242 260
@@ -443,7 +461,8 @@ namespace OpenSim.Region.Framework.Scenes
443 get 461 get
444 { 462 {
445 PhysicsActor actor = m_physicsActor; 463 PhysicsActor actor = m_physicsActor;
446 if (actor != null) 464// if (actor != null)
465 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
447 m_pos = actor.Position; 466 m_pos = actor.Position;
448 else 467 else
449 { 468 {
@@ -492,7 +511,8 @@ namespace OpenSim.Region.Framework.Scenes
492 } 511 }
493 } 512 }
494 513
495 m_pos = value; 514 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
515 m_pos = value;
496 m_parentPosition = Vector3.Zero; 516 m_parentPosition = Vector3.Zero;
497 } 517 }
498 } 518 }
@@ -536,10 +556,39 @@ namespace OpenSim.Region.Framework.Scenes
536 } 556 }
537 } 557 }
538 558
559 public Quaternion OffsetRotation
560 {
561 get { return m_offsetRotation; }
562 set { m_offsetRotation = value; }
563 }
564
539 public Quaternion Rotation 565 public Quaternion Rotation
540 { 566 {
541 get { return m_bodyRot; } 567 get {
542 set { m_bodyRot = value; } 568 if (m_parentID != 0)
569 {
570 if (m_offsetRotation != null)
571 {
572 return m_offsetRotation;
573 }
574 else
575 {
576 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
577 }
578
579 }
580 else
581 {
582 return m_bodyRot;
583 }
584 }
585 set {
586 m_bodyRot = value;
587 if (m_parentID != 0)
588 {
589 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
590 }
591 }
543 } 592 }
544 593
545 public Quaternion PreviousRotation 594 public Quaternion PreviousRotation
@@ -564,11 +613,21 @@ namespace OpenSim.Region.Framework.Scenes
564 613
565 private uint m_parentID; 614 private uint m_parentID;
566 615
616
617 private UUID m_linkedPrim;
618
567 public uint ParentID 619 public uint ParentID
568 { 620 {
569 get { return m_parentID; } 621 get { return m_parentID; }
570 set { m_parentID = value; } 622 set { m_parentID = value; }
571 } 623 }
624
625 public UUID LinkedPrim
626 {
627 get { return m_linkedPrim; }
628 set { m_linkedPrim = value; }
629 }
630
572 public float Health 631 public float Health
573 { 632 {
574 get { return m_health; } 633 get { return m_health; }
@@ -690,7 +749,7 @@ namespace OpenSim.Region.Framework.Scenes
690 CreateSceneViewer(); 749 CreateSceneViewer();
691 m_animator = new ScenePresenceAnimator(this); 750 m_animator = new ScenePresenceAnimator(this);
692 } 751 }
693 752
694 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 753 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
695 { 754 {
696 m_rootRegionHandle = reginfo.RegionHandle; 755 m_rootRegionHandle = reginfo.RegionHandle;
@@ -722,10 +781,7 @@ namespace OpenSim.Region.Framework.Scenes
722 m_reprioritization_timer.AutoReset = false; 781 m_reprioritization_timer.AutoReset = false;
723 782
724 AdjustKnownSeeds(); 783 AdjustKnownSeeds();
725
726 // TODO: I think, this won't send anything, as we are still a child here...
727 Animator.TrySetMovementAnimation("STAND"); 784 Animator.TrySetMovementAnimation("STAND");
728
729 // we created a new ScenePresence (a new child agent) in a fresh region. 785 // we created a new ScenePresence (a new child agent) in a fresh region.
730 // Request info about all the (root) agents in this region 786 // Request info about all the (root) agents in this region
731 // Note: This won't send data *to* other clients in that region (children don't send) 787 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -776,25 +832,47 @@ namespace OpenSim.Region.Framework.Scenes
776 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 832 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
777 Dir_Vectors[4] = Vector3.UnitZ; //UP 833 Dir_Vectors[4] = Vector3.UnitZ; //UP
778 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 834 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
779 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 835 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
780 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 836 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
781 Dir_Vectors[7] = -Vector3.UnitX; //BACK 837 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
838 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
839 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
782 } 840 }
783 841
784 private Vector3[] GetWalkDirectionVectors() 842 private Vector3[] GetWalkDirectionVectors()
785 { 843 {
786 Vector3[] vector = new Vector3[9]; 844 Vector3[] vector = new Vector3[11];
787 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 845 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
788 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 846 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
789 vector[2] = Vector3.UnitY; //LEFT 847 vector[2] = Vector3.UnitY; //LEFT
790 vector[3] = -Vector3.UnitY; //RIGHT 848 vector[3] = -Vector3.UnitY; //RIGHT
791 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 849 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
792 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 850 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
793 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 851 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
794 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 852 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
795 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 853 vector[8] = Vector3.UnitY; //LEFT_NUDGE
854 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
855 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
796 return vector; 856 return vector;
797 } 857 }
858
859 private bool[] GetDirectionIsNudge()
860 {
861 bool[] isNudge = new bool[11];
862 isNudge[0] = false; //FORWARD
863 isNudge[1] = false; //BACK
864 isNudge[2] = false; //LEFT
865 isNudge[3] = false; //RIGHT
866 isNudge[4] = false; //UP
867 isNudge[5] = false; //DOWN
868 isNudge[6] = true; //FORWARD_NUDGE
869 isNudge[7] = true; //BACK_NUDGE
870 isNudge[8] = true; //LEFT_NUDGE
871 isNudge[9] = true; //RIGHT_NUDGE
872 isNudge[10] = true; //DOWN_Nudge
873 return isNudge;
874 }
875
798 876
799 #endregion 877 #endregion
800 878
@@ -856,6 +934,54 @@ namespace OpenSim.Region.Framework.Scenes
856 pos.Y = crossedBorder.BorderLine.Z - 1; 934 pos.Y = crossedBorder.BorderLine.Z - 1;
857 } 935 }
858 936
937 //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
938 //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
939 //they'll bypass the landing point. But I can't think of any decent way of fixing this.
940 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
941 if (land != null)
942 {
943 if (KnownChildRegionHandles.Count == 0)
944 {
945 //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
946 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
947 {
948 pos = land.LandData.UserLocation;
949 }
950 }
951
952 land.SendLandUpdateToClient(ControllingClient);
953 }
954
955 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
956 {
957 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
958
959 if (pos.X < 0)
960 {
961 emergencyPos.X = (int)Constants.RegionSize + pos.X;
962 if (!(pos.Y < 0))
963 emergencyPos.Y = pos.Y;
964 if (!(pos.Z < 0))
965 emergencyPos.Z = pos.Z;
966 }
967 if (pos.Y < 0)
968 {
969 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
970 if (!(pos.X < 0))
971 emergencyPos.X = pos.X;
972 if (!(pos.Z < 0))
973 emergencyPos.Z = pos.Z;
974 }
975 if (pos.Z < 0)
976 {
977 emergencyPos.Z = 128;
978 if (!(pos.Y < 0))
979 emergencyPos.Y = pos.Y;
980 if (!(pos.X < 0))
981 emergencyPos.X = pos.X;
982 }
983 }
984
859 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 985 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
860 { 986 {
861 m_log.WarnFormat( 987 m_log.WarnFormat(
@@ -984,12 +1110,17 @@ namespace OpenSim.Region.Framework.Scenes
984 { 1110 {
985 if (PhysicsActor != null) 1111 if (PhysicsActor != null)
986 { 1112 {
987 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1113 try
988 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1114 {
989 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1115 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
990 m_physicsActor.UnSubscribeEvents(); 1116 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
991 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1117 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
992 PhysicsActor = null; 1118 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1119 m_physicsActor.UnSubscribeEvents();
1120 PhysicsActor = null;
1121 }
1122 catch
1123 { }
993 } 1124 }
994 } 1125 }
995 1126
@@ -1000,9 +1131,10 @@ namespace OpenSim.Region.Framework.Scenes
1000 public void Teleport(Vector3 pos) 1131 public void Teleport(Vector3 pos)
1001 { 1132 {
1002 bool isFlying = false; 1133 bool isFlying = false;
1134
1003 if (m_physicsActor != null) 1135 if (m_physicsActor != null)
1004 isFlying = m_physicsActor.Flying; 1136 isFlying = m_physicsActor.Flying;
1005 1137
1006 RemoveFromPhysicalScene(); 1138 RemoveFromPhysicalScene();
1007 Velocity = Vector3.Zero; 1139 Velocity = Vector3.Zero;
1008 AbsolutePosition = pos; 1140 AbsolutePosition = pos;
@@ -1014,6 +1146,7 @@ namespace OpenSim.Region.Framework.Scenes
1014 } 1146 }
1015 1147
1016 SendTerseUpdateToAllClients(); 1148 SendTerseUpdateToAllClients();
1149
1017 } 1150 }
1018 1151
1019 public void TeleportWithMomentum(Vector3 pos) 1152 public void TeleportWithMomentum(Vector3 pos)
@@ -1232,6 +1365,7 @@ namespace OpenSim.Region.Framework.Scenes
1232 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1365 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1233 1366
1234 m_pos = m_LastFinitePos; 1367 m_pos = m_LastFinitePos;
1368
1235 if (!m_pos.IsFinite()) 1369 if (!m_pos.IsFinite())
1236 { 1370 {
1237 m_pos.X = 127f; 1371 m_pos.X = 127f;
@@ -1298,7 +1432,6 @@ namespace OpenSim.Region.Framework.Scenes
1298 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1432 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1299 } 1433 }
1300 } 1434 }
1301
1302 lock (scriptedcontrols) 1435 lock (scriptedcontrols)
1303 { 1436 {
1304 if (scriptedcontrols.Count > 0) 1437 if (scriptedcontrols.Count > 0)
@@ -1313,6 +1446,9 @@ namespace OpenSim.Region.Framework.Scenes
1313 1446
1314 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1447 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1315 { 1448 {
1449 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1450 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1451
1316 // TODO: This doesn't prevent the user from walking yet. 1452 // TODO: This doesn't prevent the user from walking yet.
1317 // Setting parent ID would fix this, if we knew what value 1453 // Setting parent ID would fix this, if we knew what value
1318 // to use. Or we could add a m_isSitting variable. 1454 // to use. Or we could add a m_isSitting variable.
@@ -1361,12 +1497,20 @@ namespace OpenSim.Region.Framework.Scenes
1361 if (actor.Flying != oldflying) 1497 if (actor.Flying != oldflying)
1362 update_movementflag = true; 1498 update_movementflag = true;
1363 1499
1500 if (m_animator.m_jumping) // add for jumping
1501 update_movementflag = true;
1502
1364 if (q != m_bodyRot) 1503 if (q != m_bodyRot)
1365 { 1504 {
1366 m_bodyRot = q; 1505 m_bodyRot = q;
1367 update_rotation = true; 1506 update_rotation = true;
1368 } 1507 }
1369 1508
1509 //guilty until proven innocent..
1510 bool Nudging = true;
1511 //Basically, if there is at least one non-nudge control then we don't need
1512 //to worry about stopping the avatar
1513
1370 if (m_parentID == 0) 1514 if (m_parentID == 0)
1371 { 1515 {
1372 bool bAllowUpdateMoveToPosition = false; 1516 bool bAllowUpdateMoveToPosition = false;
@@ -1381,9 +1525,12 @@ namespace OpenSim.Region.Framework.Scenes
1381 else 1525 else
1382 dirVectors = Dir_Vectors; 1526 dirVectors = Dir_Vectors;
1383 1527
1384 // The fact that m_movementflag is a byte needs to be fixed 1528 bool[] isNudge = GetDirectionIsNudge();
1385 // it really should be a uint 1529
1386 uint nudgehack = 250; 1530
1531
1532
1533
1387 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1534 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1388 { 1535 {
1389 if (((uint)flags & (uint)DCF) != 0) 1536 if (((uint)flags & (uint)DCF) != 0)
@@ -1393,40 +1540,28 @@ namespace OpenSim.Region.Framework.Scenes
1393 try 1540 try
1394 { 1541 {
1395 agent_control_v3 += dirVectors[i]; 1542 agent_control_v3 += dirVectors[i];
1396 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1543 if (isNudge[i] == false)
1544 {
1545 Nudging = false;
1546 }
1397 } 1547 }
1398 catch (IndexOutOfRangeException) 1548 catch (IndexOutOfRangeException)
1399 { 1549 {
1400 // Why did I get this? 1550 // Why did I get this?
1401 } 1551 }
1402 1552
1403 if ((m_movementflag & (byte)(uint)DCF) == 0) 1553 if ((m_movementflag & (uint)DCF) == 0)
1404 { 1554 {
1405 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1406 {
1407 m_movementflag |= (byte)nudgehack;
1408 }
1409 m_movementflag += (byte)(uint)DCF; 1555 m_movementflag += (byte)(uint)DCF;
1410 update_movementflag = true; 1556 update_movementflag = true;
1411 } 1557 }
1412 } 1558 }
1413 else 1559 else
1414 { 1560 {
1415 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1561 if ((m_movementflag & (uint)DCF) != 0)
1416 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1417 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1418 ) // This or is for Nudge forward
1419 { 1562 {
1420 m_movementflag -= ((byte)(uint)DCF); 1563 m_movementflag -= (byte)(uint)DCF;
1421
1422 update_movementflag = true; 1564 update_movementflag = true;
1423 /*
1424 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1425 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1426 {
1427 m_log.Debug("Removed Hack flag");
1428 }
1429 */
1430 } 1565 }
1431 else 1566 else
1432 { 1567 {
@@ -1435,7 +1570,6 @@ namespace OpenSim.Region.Framework.Scenes
1435 } 1570 }
1436 i++; 1571 i++;
1437 } 1572 }
1438
1439 //Paupaw:Do Proper PID for Autopilot here 1573 //Paupaw:Do Proper PID for Autopilot here
1440 if (bResetMoveToPosition) 1574 if (bResetMoveToPosition)
1441 { 1575 {
@@ -1470,6 +1604,9 @@ namespace OpenSim.Region.Framework.Scenes
1470 // Ignore z component of vector 1604 // Ignore z component of vector
1471 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1605 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1472 LocalVectorToTarget2D.Normalize(); 1606 LocalVectorToTarget2D.Normalize();
1607
1608 //We're not nudging
1609 Nudging = false;
1473 agent_control_v3 += LocalVectorToTarget2D; 1610 agent_control_v3 += LocalVectorToTarget2D;
1474 1611
1475 // update avatar movement flags. the avatar coordinate system is as follows: 1612 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1560,13 +1697,13 @@ namespace OpenSim.Region.Framework.Scenes
1560 // m_log.DebugFormat( 1697 // m_log.DebugFormat(
1561 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1698 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1562 1699
1563 AddNewMovement(agent_control_v3, q); 1700 AddNewMovement(agent_control_v3, q, Nudging);
1564 1701
1565 1702
1566 } 1703 }
1567 } 1704 }
1568 1705
1569 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1706 if (update_movementflag && !SitGround)
1570 Animator.UpdateMovementAnimations(); 1707 Animator.UpdateMovementAnimations();
1571 1708
1572 m_scene.EventManager.TriggerOnClientMovement(this); 1709 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1581,7 +1718,6 @@ namespace OpenSim.Region.Framework.Scenes
1581 m_sitAtAutoTarget = false; 1718 m_sitAtAutoTarget = false;
1582 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1719 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1583 //proxy.PCode = (byte)PCode.ParticleSystem; 1720 //proxy.PCode = (byte)PCode.ParticleSystem;
1584
1585 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1721 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1586 proxyObjectGroup.AttachToScene(m_scene); 1722 proxyObjectGroup.AttachToScene(m_scene);
1587 1723
@@ -1623,7 +1759,7 @@ namespace OpenSim.Region.Framework.Scenes
1623 } 1759 }
1624 m_moveToPositionInProgress = true; 1760 m_moveToPositionInProgress = true;
1625 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1761 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1626 } 1762 }
1627 catch (Exception ex) 1763 catch (Exception ex)
1628 { 1764 {
1629 //Why did I get this error? 1765 //Why did I get this error?
@@ -1645,7 +1781,7 @@ namespace OpenSim.Region.Framework.Scenes
1645 Velocity = Vector3.Zero; 1781 Velocity = Vector3.Zero;
1646 SendAvatarDataToAllAgents(); 1782 SendAvatarDataToAllAgents();
1647 1783
1648 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1784 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1649 } 1785 }
1650 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1786 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1651 m_requestedSitTargetUUID = UUID.Zero; 1787 m_requestedSitTargetUUID = UUID.Zero;
@@ -1682,42 +1818,77 @@ namespace OpenSim.Region.Framework.Scenes
1682 1818
1683 if (m_parentID != 0) 1819 if (m_parentID != 0)
1684 { 1820 {
1685 m_log.Debug("StandupCode Executed"); 1821 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1686 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1687 if (part != null) 1822 if (part != null)
1688 { 1823 {
1824 part.TaskInventory.LockItemsForRead(true);
1689 TaskInventoryDictionary taskIDict = part.TaskInventory; 1825 TaskInventoryDictionary taskIDict = part.TaskInventory;
1690 if (taskIDict != null) 1826 if (taskIDict != null)
1691 { 1827 {
1692 lock (taskIDict) 1828 foreach (UUID taskID in taskIDict.Keys)
1693 { 1829 {
1694 foreach (UUID taskID in taskIDict.Keys) 1830 UnRegisterControlEventsToScript(LocalId, taskID);
1695 { 1831 taskIDict[taskID].PermsMask &= ~(
1696 UnRegisterControlEventsToScript(LocalId, taskID); 1832 2048 | //PERMISSION_CONTROL_CAMERA
1697 taskIDict[taskID].PermsMask &= ~( 1833 4); // PERMISSION_TAKE_CONTROLS
1698 2048 | //PERMISSION_CONTROL_CAMERA
1699 4); // PERMISSION_TAKE_CONTROLS
1700 }
1701 } 1834 }
1702
1703 } 1835 }
1836 part.TaskInventory.LockItemsForRead(false);
1704 // Reset sit target. 1837 // Reset sit target.
1705 if (part.GetAvatarOnSitTarget() == UUID) 1838 if (part.GetAvatarOnSitTarget() == UUID)
1706 part.SetAvatarOnSitTarget(UUID.Zero); 1839 part.SetAvatarOnSitTarget(UUID.Zero);
1707
1708 m_parentPosition = part.GetWorldPosition(); 1840 m_parentPosition = part.GetWorldPosition();
1709 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1841 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1710 } 1842 }
1843 // part.GetWorldRotation() is the rotation of the object being sat on
1844 // Rotation is the sittiing Av's rotation
1845
1846 Quaternion partRot;
1847// if (part.LinkNum == 1)
1848// { // Root prim of linkset
1849// partRot = part.ParentGroup.RootPart.RotationOffset;
1850// }
1851// else
1852// { // single or child prim
1853
1854// }
1855 if (part == null) //CW: Part may be gone. llDie() for example.
1856 {
1857 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1858 }
1859 else
1860 {
1861 partRot = part.GetWorldRotation();
1862 }
1711 1863
1864 Quaternion partIRot = Quaternion.Inverse(partRot);
1865
1866 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1867 Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
1868
1869
1712 if (m_physicsActor == null) 1870 if (m_physicsActor == null)
1713 { 1871 {
1714 AddToPhysicalScene(false); 1872 AddToPhysicalScene(false);
1715 } 1873 }
1716 1874 //CW: If the part isn't null then we can set the current position
1717 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1875 if (part != null)
1718 m_parentPosition = Vector3.Zero; 1876 {
1719 1877 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1720 m_parentID = 0; 1878 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1879 part.IsOccupied = false;
1880 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1881 }
1882 else
1883 {
1884 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1885 AbsolutePosition = m_lastWorldPosition;
1886 }
1887
1888 m_parentPosition = Vector3.Zero;
1889 m_parentID = 0;
1890 m_linkedPrim = UUID.Zero;
1891 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1721 SendAvatarDataToAllAgents(); 1892 SendAvatarDataToAllAgents();
1722 m_requestedSitTargetID = 0; 1893 m_requestedSitTargetID = 0;
1723 if (m_physicsActor != null && m_appearance != null) 1894 if (m_physicsActor != null && m_appearance != null)
@@ -1726,7 +1897,6 @@ namespace OpenSim.Region.Framework.Scenes
1726 SetHeight(m_appearance.AvatarHeight); 1897 SetHeight(m_appearance.AvatarHeight);
1727 } 1898 }
1728 } 1899 }
1729
1730 Animator.TrySetMovementAnimation("STAND"); 1900 Animator.TrySetMovementAnimation("STAND");
1731 } 1901 }
1732 1902
@@ -1757,13 +1927,9 @@ namespace OpenSim.Region.Framework.Scenes
1757 Vector3 avSitOffSet = part.SitTargetPosition; 1927 Vector3 avSitOffSet = part.SitTargetPosition;
1758 Quaternion avSitOrientation = part.SitTargetOrientation; 1928 Quaternion avSitOrientation = part.SitTargetOrientation;
1759 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1929 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1760 1930 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1761 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1931 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1762 bool SitTargetisSet = 1932 if (SitTargetisSet && !SitTargetOccupied)
1763 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1764 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1765
1766 if (SitTargetisSet && SitTargetUnOccupied)
1767 { 1933 {
1768 //switch the target to this prim 1934 //switch the target to this prim
1769 return part; 1935 return part;
@@ -1777,84 +1943,164 @@ namespace OpenSim.Region.Framework.Scenes
1777 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1943 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1778 { 1944 {
1779 bool autopilot = true; 1945 bool autopilot = true;
1946 Vector3 autopilotTarget = new Vector3();
1947 Quaternion sitOrientation = Quaternion.Identity;
1780 Vector3 pos = new Vector3(); 1948 Vector3 pos = new Vector3();
1781 Quaternion sitOrientation = pSitOrientation;
1782 Vector3 cameraEyeOffset = Vector3.Zero; 1949 Vector3 cameraEyeOffset = Vector3.Zero;
1783 Vector3 cameraAtOffset = Vector3.Zero; 1950 Vector3 cameraAtOffset = Vector3.Zero;
1784 bool forceMouselook = false; 1951 bool forceMouselook = false;
1785 1952
1786 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1953 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1787 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1954 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1788 if (part != null) 1955 if (part == null) return;
1789 { 1956
1790 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1957 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1791 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1958 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1792 1959
1793 // Is a sit target available? 1960 // part is the prim to sit on
1794 Vector3 avSitOffSet = part.SitTargetPosition; 1961 // offset is the world-ref vector distance from that prim center to the click-spot
1795 Quaternion avSitOrientation = part.SitTargetOrientation; 1962 // UUID is the UUID of the Avatar doing the clicking
1796 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1963
1797 1964 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1798 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1965
1799 bool SitTargetisSet = 1966 // Is a sit target available?
1800 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1967 Vector3 avSitOffSet = part.SitTargetPosition;
1801 ( 1968 Quaternion avSitOrientation = part.SitTargetOrientation;
1802 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1969
1803 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1970 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1804 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1971 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1805 ) 1972 Quaternion partRot;
1806 )); 1973// if (part.LinkNum == 1)
1807 1974// { // Root prim of linkset
1808 if (SitTargetisSet && SitTargetUnOccupied) 1975// partRot = part.ParentGroup.RootPart.RotationOffset;
1809 { 1976// }
1810 part.SetAvatarOnSitTarget(UUID); 1977// else
1811 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 1978// { // single or child prim
1812 sitOrientation = avSitOrientation; 1979 partRot = part.GetWorldRotation();
1813 autopilot = false; 1980// }
1814 } 1981 Quaternion partIRot = Quaternion.Inverse(partRot);
1815 1982//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1816 pos = part.AbsolutePosition + offset; 1983 // Sit analysis rewritten by KF 091125
1817 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 1984 if (SitTargetisSet) // scipted sit
1818 //{ 1985 {
1819 // offset = pos; 1986 if (!part.IsOccupied)
1820 //autopilot = false; 1987 {
1821 //} 1988//Console.WriteLine("Scripted, unoccupied");
1822 if (m_physicsActor != null) 1989 part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
1823 { 1990 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1824 // If we're not using the client autopilot, we're immediately warping the avatar to the location 1991
1825 // We can remove the physicsActor until they stand up. 1992 Quaternion nrot = avSitOrientation;
1826 m_sitAvatarHeight = m_physicsActor.Size.Z; 1993 if (!part.IsRoot)
1827
1828 if (autopilot)
1829 { 1994 {
1830 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 1995 nrot = part.RotationOffset * avSitOrientation;
1831 {
1832 autopilot = false;
1833
1834 RemoveFromPhysicalScene();
1835 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1836 }
1837 } 1996 }
1838 else 1997 sitOrientation = nrot; // Change rotatione to the scripted one
1998 OffsetRotation = nrot;
1999 autopilot = false; // Jump direct to scripted llSitPos()
2000 }
2001 else
2002 {
2003//Console.WriteLine("Scripted, occupied");
2004 return;
2005 }
2006 }
2007 else // Not Scripted
2008 {
2009 if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
2010 {
2011 // large prim & offset, ignore if other Avs sitting
2012// offset.Z -= 0.05f;
2013 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
2014 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
2015
2016//Console.WriteLine(" offset ={0}", offset);
2017//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
2018//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
2019
2020 }
2021 else // small offset
2022 {
2023//Console.WriteLine("Small offset");
2024 if (!part.IsOccupied)
2025 {
2026 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2027 autopilotTarget = part.AbsolutePosition;
2028//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2029 }
2030 else return; // occupied small
2031 } // end large/small
2032 } // end Scripted/not
2033 cameraAtOffset = part.GetCameraAtOffset();
2034 cameraEyeOffset = part.GetCameraEyeOffset();
2035 forceMouselook = part.GetForceMouselook();
2036 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2037 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2038
2039 if (m_physicsActor != null)
2040 {
2041 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2042 // We can remove the physicsActor until they stand up.
2043 m_sitAvatarHeight = m_physicsActor.Size.Z;
2044 if (autopilot)
2045 { // its not a scripted sit
2046// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2047 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1839 { 2048 {
2049 autopilot = false; // close enough
2050 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2051 Not using the part's position because returning the AV to the last known standing
2052 position is likely to be more friendly, isn't it? */
1840 RemoveFromPhysicalScene(); 2053 RemoveFromPhysicalScene();
1841 } 2054 Velocity = Vector3.Zero;
2055 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2056 } // else the autopilot will get us close
2057 }
2058 else
2059 { // its a scripted sit
2060 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2061 I *am* using the part's position this time because we have no real idea how far away
2062 the avatar is from the sit target. */
2063 RemoveFromPhysicalScene();
2064 Velocity = Vector3.Zero;
1842 } 2065 }
1843
1844 cameraAtOffset = part.GetCameraAtOffset();
1845 cameraEyeOffset = part.GetCameraEyeOffset();
1846 forceMouselook = part.GetForceMouselook();
1847 } 2066 }
1848 2067 else return; // physactor is null!
1849 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2068
1850 m_requestedSitTargetUUID = targetID; 2069 Vector3 offsetr; // = offset * partIRot;
2070 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2071 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2072 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2073 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2074 //offsetr = offset * partIRot;
2075//
2076 // else
2077 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2078 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2079 // (offset * partRot);
2080 // }
2081
2082//Console.WriteLine(" ");
2083//Console.WriteLine("link number ={0}", part.LinkNum);
2084//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2085//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2086//Console.WriteLine("Click offst ={0}", offset);
2087//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2088//Console.WriteLine("offsetr ={0}", offsetr);
2089//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2090//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2091
2092 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2093 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2094
2095 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1851 // This calls HandleAgentSit twice, once from here, and the client calls 2096 // This calls HandleAgentSit twice, once from here, and the client calls
1852 // HandleAgentSit itself after it gets to the location 2097 // HandleAgentSit itself after it gets to the location
1853 // It doesn't get to the location until we've moved them there though 2098 // It doesn't get to the location until we've moved them there though
1854 // which happens in HandleAgentSit :P 2099 // which happens in HandleAgentSit :P
1855 m_autopilotMoving = autopilot; 2100 m_autopilotMoving = autopilot;
1856 m_autoPilotTarget = pos; 2101 m_autoPilotTarget = autopilotTarget;
1857 m_sitAtAutoTarget = autopilot; 2102 m_sitAtAutoTarget = autopilot;
2103 m_initialSitTarget = autopilotTarget;
1858 if (!autopilot) 2104 if (!autopilot)
1859 HandleAgentSit(remoteClient, UUID); 2105 HandleAgentSit(remoteClient, UUID);
1860 } 2106 }
@@ -2149,47 +2395,130 @@ namespace OpenSim.Region.Framework.Scenes
2149 { 2395 {
2150 if (part != null) 2396 if (part != null)
2151 { 2397 {
2398//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2152 if (part.GetAvatarOnSitTarget() == UUID) 2399 if (part.GetAvatarOnSitTarget() == UUID)
2153 { 2400 {
2401//Console.WriteLine("Scripted Sit");
2402 // Scripted sit
2154 Vector3 sitTargetPos = part.SitTargetPosition; 2403 Vector3 sitTargetPos = part.SitTargetPosition;
2155 Quaternion sitTargetOrient = part.SitTargetOrientation; 2404 Quaternion sitTargetOrient = part.SitTargetOrientation;
2156
2157 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2158 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2159
2160 //Quaternion result = (sitTargetOrient * vq) * nq;
2161
2162 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2405 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2163 m_pos += SIT_TARGET_ADJUSTMENT; 2406 m_pos += SIT_TARGET_ADJUSTMENT;
2407 if (!part.IsRoot)
2408 {
2409 m_pos *= part.RotationOffset;
2410 }
2164 m_bodyRot = sitTargetOrient; 2411 m_bodyRot = sitTargetOrient;
2165 //Rotation = sitTargetOrient;
2166 m_parentPosition = part.AbsolutePosition; 2412 m_parentPosition = part.AbsolutePosition;
2167 2413 part.IsOccupied = true;
2168 //SendTerseUpdateToAllClients(); 2414 part.ParentGroup.AddAvatar(agentID);
2169 } 2415 }
2170 else 2416 else
2171 { 2417 {
2172 m_pos -= part.AbsolutePosition; 2418 // if m_avUnscriptedSitPos is zero then Av sits above center
2419 // Else Av sits at m_avUnscriptedSitPos
2420
2421 // Non-scripted sit by Kitto Flora 21Nov09
2422 // Calculate angle of line from prim to Av
2423 Quaternion partIRot;
2424// if (part.LinkNum == 1)
2425// { // Root prim of linkset
2426// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2427// }
2428// else
2429// { // single or child prim
2430 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2431// }
2432 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2433 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2434 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2435 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2436 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2437 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2438 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2439 // Av sits at world euler <0,0, z>, translated by part rotation
2440 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2441
2173 m_parentPosition = part.AbsolutePosition; 2442 m_parentPosition = part.AbsolutePosition;
2174 } 2443 part.IsOccupied = true;
2444 part.ParentGroup.AddAvatar(agentID);
2445 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2446 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2447 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2448 m_avUnscriptedSitPos; // adds click offset, if any
2449 //Set up raytrace to find top surface of prim
2450 Vector3 size = part.Scale;
2451 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2452 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2453 Vector3 down = new Vector3(0f, 0f, -1f);
2454//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2455 m_scene.PhysicsScene.RaycastWorld(
2456 start, // Vector3 position,
2457 down, // Vector3 direction,
2458 mag, // float length,
2459 SitAltitudeCallback); // retMethod
2460 } // end scripted/not
2175 } 2461 }
2176 else 2462 else // no Av
2177 { 2463 {
2178 return; 2464 return;
2179 } 2465 }
2180 } 2466 }
2181 m_parentID = m_requestedSitTargetID;
2182 2467
2468 //We want our offsets to reference the root prim, not the child we may have sat on
2469 if (!part.IsRoot)
2470 {
2471 m_parentID = part.ParentGroup.RootPart.LocalId;
2472 m_pos += part.OffsetPosition;
2473 }
2474 else
2475 {
2476 m_parentID = m_requestedSitTargetID;
2477 }
2478
2479 m_linkedPrim = part.UUID;
2480 if (part.GetAvatarOnSitTarget() != UUID)
2481 {
2482 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2483 }
2183 Velocity = Vector3.Zero; 2484 Velocity = Vector3.Zero;
2184 RemoveFromPhysicalScene(); 2485 RemoveFromPhysicalScene();
2185
2186 Animator.TrySetMovementAnimation(sitAnimation); 2486 Animator.TrySetMovementAnimation(sitAnimation);
2187 SendAvatarDataToAllAgents(); 2487 SendAvatarDataToAllAgents();
2188 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2189 // So we're also sending a terse update (which has avatar rotation)
2190 // [Update] We do now.
2191 //SendTerseUpdateToAllClients(); 2488 //SendTerseUpdateToAllClients();
2192 } 2489 }
2490
2491 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2492 {
2493 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2494 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2495 if(hitYN)
2496 {
2497 // m_pos = Av offset from prim center to make look like on center
2498 // m_parentPosition = Actual center pos of prim
2499 // collisionPoint = spot on prim where we want to sit
2500 // collisionPoint.Z = global sit surface height
2501 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2502 Quaternion partIRot;
2503// if (part.LinkNum == 1)
2504/// { // Root prim of linkset
2505// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2506// }
2507// else
2508// { // single or child prim
2509 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2510// }
2511 if (m_initialSitTarget != null)
2512 {
2513 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2514 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2515 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2516 m_pos += offset;
2517 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2518 }
2519
2520 }
2521 } // End SitAltitudeCallback KF.
2193 2522
2194 /// <summary> 2523 /// <summary>
2195 /// Event handler for the 'Always run' setting on the client 2524 /// Event handler for the 'Always run' setting on the client
@@ -2219,7 +2548,7 @@ namespace OpenSim.Region.Framework.Scenes
2219 /// </summary> 2548 /// </summary>
2220 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2549 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2221 /// <param name="rotation">The direction in which this avatar should now face. 2550 /// <param name="rotation">The direction in which this avatar should now face.
2222 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2551 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2223 { 2552 {
2224 if (m_isChildAgent) 2553 if (m_isChildAgent)
2225 { 2554 {
@@ -2260,15 +2589,26 @@ namespace OpenSim.Region.Framework.Scenes
2260 Rotation = rotation; 2589 Rotation = rotation;
2261 Vector3 direc = vec * rotation; 2590 Vector3 direc = vec * rotation;
2262 direc.Normalize(); 2591 direc.Normalize();
2592 PhysicsActor actor = m_physicsActor;
2593
2594 if (actor.Flying != m_flyingOld) // add for fly velocity control
2595 {
2596 m_flyingOld = actor.Flying; // add for fly velocity control
2597 if (!actor.Flying) m_wasFlying = true; // add for fly velocity control
2598 }
2599
2600 if (m_physicsActor.IsColliding == true) m_wasFlying = false; // add for fly velocity control
2601
2602 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2263 2603
2264 direc *= 0.03f * 128f * m_speedModifier; 2604 direc *= 0.03f * 128f * m_speedModifier;
2265 2605
2266 PhysicsActor actor = m_physicsActor;
2267 if (actor != null) 2606 if (actor != null)
2268 { 2607 {
2269 if (actor.Flying) 2608 if (actor.Flying)
2270 { 2609 {
2271 direc *= 4.0f; 2610// rm speed mod direc *= 4.0f;
2611 direc *= 5.2f; // for speed mod
2272 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2612 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2273 //bool colliding = (m_physicsActor.IsColliding==true); 2613 //bool colliding = (m_physicsActor.IsColliding==true);
2274 //if (controlland) 2614 //if (controlland)
@@ -2281,22 +2621,34 @@ namespace OpenSim.Region.Framework.Scenes
2281 // m_log.Info("[AGENT]: Stop FLying"); 2621 // m_log.Info("[AGENT]: Stop FLying");
2282 //} 2622 //}
2283 } 2623 }
2624 if (Animator.m_falling && m_wasFlying) // if falling from flying, disable motion add
2625 {
2626 direc *= 0.0f;
2627 }
2628 /* This jumping section removed to SPA
2284 else if (!actor.Flying && actor.IsColliding) 2629 else if (!actor.Flying && actor.IsColliding)
2285 { 2630 {
2286 if (direc.Z > 2.0f) 2631 if (direc.Z > 2.0f)
2287 { 2632 {
2288 direc.Z *= 3.0f; 2633 if(m_animator.m_animTickJump == -1)
2289 2634 {
2290 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2635 direc.Z *= 3.0f; // jump
2291 Animator.TrySetMovementAnimation("PREJUMP"); 2636 }
2292 Animator.TrySetMovementAnimation("JUMP"); 2637 else
2638 {
2639 direc.Z *= 0.1f; // prejump
2640 }
2641 / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2642 Animator.TrySetMovementAnimation("PREJUMP");
2643 Animator.TrySetMovementAnimation("JUMP");
2644 * /
2293 } 2645 }
2294 } 2646 } */
2295 } 2647 }
2296 2648
2297 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2649 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2298 m_forceToApply = direc; 2650 m_forceToApply = direc;
2299 2651 m_isNudging = Nudging;
2300 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2652 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2301 } 2653 }
2302 2654
@@ -2311,7 +2663,7 @@ namespace OpenSim.Region.Framework.Scenes
2311 const float POSITION_TOLERANCE = 0.05f; 2663 const float POSITION_TOLERANCE = 0.05f;
2312 //const int TIME_MS_TOLERANCE = 3000; 2664 //const int TIME_MS_TOLERANCE = 3000;
2313 2665
2314 SendPrimUpdates(); 2666
2315 2667
2316 if (m_isChildAgent == false) 2668 if (m_isChildAgent == false)
2317 { 2669 {
@@ -2341,6 +2693,9 @@ namespace OpenSim.Region.Framework.Scenes
2341 CheckForBorderCrossing(); 2693 CheckForBorderCrossing();
2342 CheckForSignificantMovement(); // sends update to the modules. 2694 CheckForSignificantMovement(); // sends update to the modules.
2343 } 2695 }
2696
2697 //Sending prim updates AFTER the avatar terse updates are sent
2698 SendPrimUpdates();
2344 } 2699 }
2345 2700
2346 #endregion 2701 #endregion
@@ -3103,6 +3458,7 @@ namespace OpenSim.Region.Framework.Scenes
3103 m_callbackURI = cAgent.CallbackURI; 3458 m_callbackURI = cAgent.CallbackURI;
3104 3459
3105 m_pos = cAgent.Position; 3460 m_pos = cAgent.Position;
3461
3106 m_velocity = cAgent.Velocity; 3462 m_velocity = cAgent.Velocity;
3107 m_CameraCenter = cAgent.Center; 3463 m_CameraCenter = cAgent.Center;
3108 m_CameraAtAxis = cAgent.AtAxis; 3464 m_CameraAtAxis = cAgent.AtAxis;
@@ -3221,17 +3577,46 @@ namespace OpenSim.Region.Framework.Scenes
3221 /// </summary> 3577 /// </summary>
3222 public override void UpdateMovement() 3578 public override void UpdateMovement()
3223 { 3579 {
3224 if (m_forceToApply.HasValue) 3580 if (Animator!=null) // add for jumping
3225 { 3581 { // add for jumping
3226 Vector3 force = m_forceToApply.Value; 3582 // if (!m_animator.m_jumping) // add for jumping
3583 // { // add for jumping
3227 3584
3228 m_updateflag = true; 3585 if (m_forceToApply.HasValue) // this section realigned
3229// movementvector = force; 3586 {
3230 Velocity = force;
3231 3587
3232 m_forceToApply = null; 3588 Vector3 force = m_forceToApply.Value;
3233 } 3589 m_updateflag = true;
3234 } 3590if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3591 Velocity = force;
3592//Console.WriteLine("UM1 {0}", Velocity);
3593 m_forceToApply = null;
3594 }
3595 else
3596 {
3597 if (m_isNudging)
3598 {
3599 Vector3 force = Vector3.Zero;
3600
3601 m_updateflag = true;
3602if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3603 Velocity = force;
3604//Console.WriteLine("UM2 {0}", Velocity);
3605 m_isNudging = false;
3606 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3607 }
3608 else // add for jumping
3609 { // add for jumping
3610 Vector3 force = Vector3.Zero; // add for jumping
3611if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3612//Console.WriteLine("UM3 {0}", Velocity);
3613 Velocity = force; // add for jumping
3614 }
3615
3616 }
3617 // } // end realign
3618 } // add for jumping
3619 } // add for jumping
3235 3620
3236 /// <summary> 3621 /// <summary>
3237 /// Adds a physical representation of the avatar to the Physics plugin 3622 /// Adds a physical representation of the avatar to the Physics plugin
@@ -3245,10 +3630,8 @@ namespace OpenSim.Region.Framework.Scenes
3245 3630
3246 Vector3 pVec = AbsolutePosition; 3631 Vector3 pVec = AbsolutePosition;
3247 3632
3248 // Old bug where the height was in centimeters instead of meters
3249 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, 3633 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3250 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3634 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3251
3252 scene.AddPhysicsActorTaint(m_physicsActor); 3635 scene.AddPhysicsActorTaint(m_physicsActor);
3253 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3636 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3254 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3637 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3272,18 +3655,29 @@ namespace OpenSim.Region.Framework.Scenes
3272 { 3655 {
3273 if (e == null) 3656 if (e == null)
3274 return; 3657 return;
3275 3658
3276 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3659 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3277 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3278 // as of this comment the interval is set in AddToPhysicalScene 3660 // as of this comment the interval is set in AddToPhysicalScene
3279 if (Animator!=null) 3661 if (Animator!=null)
3280 Animator.UpdateMovementAnimations(); 3662 {
3663 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3664 { // else its will lock out other animation changes, like ground sit.
3665 Animator.UpdateMovementAnimations();
3666 m_updateCount--;
3667 }
3668 }
3281 3669
3282 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3670 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3283 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3671 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3284 3672
3285 CollisionPlane = Vector4.UnitW; 3673 CollisionPlane = Vector4.UnitW;
3286 3674
3675 if (m_lastColCount != coldata.Count)
3676 {
3677 m_updateCount = UPDATE_COUNT;
3678 m_lastColCount = coldata.Count;
3679 }
3680
3287 if (coldata.Count != 0 && Animator != null) 3681 if (coldata.Count != 0 && Animator != null)
3288 { 3682 {
3289 switch (Animator.CurrentMovementAnimation) 3683 switch (Animator.CurrentMovementAnimation)
@@ -3313,6 +3707,148 @@ namespace OpenSim.Region.Framework.Scenes
3313 } 3707 }
3314 } 3708 }
3315 3709
3710 List<uint> thisHitColliders = new List<uint>();
3711 List<uint> endedColliders = new List<uint>();
3712 List<uint> startedColliders = new List<uint>();
3713
3714 foreach (uint localid in coldata.Keys)
3715 {
3716 thisHitColliders.Add(localid);
3717 if (!m_lastColliders.Contains(localid))
3718 {
3719 startedColliders.Add(localid);
3720 }
3721 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3722 }
3723
3724 // calculate things that ended colliding
3725 foreach (uint localID in m_lastColliders)
3726 {
3727 if (!thisHitColliders.Contains(localID))
3728 {
3729 endedColliders.Add(localID);
3730 }
3731 }
3732 //add the items that started colliding this time to the last colliders list.
3733 foreach (uint localID in startedColliders)
3734 {
3735 m_lastColliders.Add(localID);
3736 }
3737 // remove things that ended colliding from the last colliders list
3738 foreach (uint localID in endedColliders)
3739 {
3740 m_lastColliders.Remove(localID);
3741 }
3742
3743 // do event notification
3744 if (startedColliders.Count > 0)
3745 {
3746 ColliderArgs StartCollidingMessage = new ColliderArgs();
3747 List<DetectedObject> colliding = new List<DetectedObject>();
3748 foreach (uint localId in startedColliders)
3749 {
3750 if (localId == 0)
3751 continue;
3752
3753 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3754 string data = "";
3755 if (obj != null)
3756 {
3757 DetectedObject detobj = new DetectedObject();
3758 detobj.keyUUID = obj.UUID;
3759 detobj.nameStr = obj.Name;
3760 detobj.ownerUUID = obj.OwnerID;
3761 detobj.posVector = obj.AbsolutePosition;
3762 detobj.rotQuat = obj.GetWorldRotation();
3763 detobj.velVector = obj.Velocity;
3764 detobj.colliderType = 0;
3765 detobj.groupUUID = obj.GroupID;
3766 colliding.Add(detobj);
3767 }
3768 }
3769
3770 if (colliding.Count > 0)
3771 {
3772 StartCollidingMessage.Colliders = colliding;
3773
3774 foreach (SceneObjectGroup att in Attachments)
3775 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3776 }
3777 }
3778
3779 if (endedColliders.Count > 0)
3780 {
3781 ColliderArgs EndCollidingMessage = new ColliderArgs();
3782 List<DetectedObject> colliding = new List<DetectedObject>();
3783 foreach (uint localId in endedColliders)
3784 {
3785 if (localId == 0)
3786 continue;
3787
3788 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3789 string data = "";
3790 if (obj != null)
3791 {
3792 DetectedObject detobj = new DetectedObject();
3793 detobj.keyUUID = obj.UUID;
3794 detobj.nameStr = obj.Name;
3795 detobj.ownerUUID = obj.OwnerID;
3796 detobj.posVector = obj.AbsolutePosition;
3797 detobj.rotQuat = obj.GetWorldRotation();
3798 detobj.velVector = obj.Velocity;
3799 detobj.colliderType = 0;
3800 detobj.groupUUID = obj.GroupID;
3801 colliding.Add(detobj);
3802 }
3803 }
3804
3805 if (colliding.Count > 0)
3806 {
3807 EndCollidingMessage.Colliders = colliding;
3808
3809 foreach (SceneObjectGroup att in Attachments)
3810 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3811 }
3812 }
3813
3814 if (thisHitColliders.Count > 0)
3815 {
3816 ColliderArgs CollidingMessage = new ColliderArgs();
3817 List<DetectedObject> colliding = new List<DetectedObject>();
3818 foreach (uint localId in thisHitColliders)
3819 {
3820 if (localId == 0)
3821 continue;
3822
3823 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3824 string data = "";
3825 if (obj != null)
3826 {
3827 DetectedObject detobj = new DetectedObject();
3828 detobj.keyUUID = obj.UUID;
3829 detobj.nameStr = obj.Name;
3830 detobj.ownerUUID = obj.OwnerID;
3831 detobj.posVector = obj.AbsolutePosition;
3832 detobj.rotQuat = obj.GetWorldRotation();
3833 detobj.velVector = obj.Velocity;
3834 detobj.colliderType = 0;
3835 detobj.groupUUID = obj.GroupID;
3836 colliding.Add(detobj);
3837 }
3838 }
3839
3840 if (colliding.Count > 0)
3841 {
3842 CollidingMessage.Colliders = colliding;
3843
3844 lock (m_attachments)
3845 {
3846 foreach (SceneObjectGroup att in m_attachments)
3847 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3848 }
3849 }
3850 }
3851
3316 if (m_invulnerable) 3852 if (m_invulnerable)
3317 return; 3853 return;
3318 3854
@@ -3738,6 +4274,39 @@ namespace OpenSim.Region.Framework.Scenes
3738 return; 4274 return;
3739 } 4275 }
3740 4276
4277 XmlDocument doc = new XmlDocument();
4278 string stateData = String.Empty;
4279
4280 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4281 if (attServ != null)
4282 {
4283 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4284 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4285 if (stateData != String.Empty)
4286 {
4287 try
4288 {
4289 doc.LoadXml(stateData);
4290 }
4291 catch { }
4292 }
4293 }
4294
4295 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4296
4297 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4298 if (nodes.Count > 0)
4299 {
4300 foreach (XmlNode n in nodes)
4301 {
4302 XmlElement elem = (XmlElement)n;
4303 string itemID = elem.GetAttribute("ItemID");
4304 string xml = elem.InnerXml;
4305
4306 itemData[new UUID(itemID)] = xml;
4307 }
4308 }
4309
3741 List<AvatarAttachment> attachments = m_appearance.GetAttachments(); 4310 List<AvatarAttachment> attachments = m_appearance.GetAttachments();
3742 foreach (AvatarAttachment attach in attachments) 4311 foreach (AvatarAttachment attach in attachments)
3743 { 4312 {
@@ -3758,7 +4327,30 @@ namespace OpenSim.Region.Framework.Scenes
3758 4327
3759 try 4328 try
3760 { 4329 {
3761 m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4330 string xmlData;
4331 XmlDocument d = new XmlDocument();
4332 UUID asset;
4333 if (itemData.TryGetValue(itemID, out xmlData))
4334 {
4335 d.LoadXml(xmlData);
4336 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4337
4338 // Rez from inventory
4339 asset
4340 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4341
4342 }
4343 else
4344 {
4345 // Rez from inventory (with a null doc to let
4346 // CHANGED_OWNER happen)
4347 asset
4348 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4349 }
4350
4351 m_log.InfoFormat(
4352 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}",
4353 p, itemID, asset);
3762 } 4354 }
3763 catch (Exception e) 4355 catch (Exception e)
3764 { 4356 {
@@ -3791,6 +4383,15 @@ namespace OpenSim.Region.Framework.Scenes
3791 m_reprioritization_called = false; 4383 m_reprioritization_called = false;
3792 } 4384 }
3793 } 4385 }
4386
4387 private Vector3 Quat2Euler(Quaternion rot){
4388 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4389 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4390 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4391 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4392 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4393 return(new Vector3(x,y,z));
4394 }
3794 4395
3795 public void SaveChangedAttachments() 4396 public void SaveChangedAttachments()
3796 { 4397 {
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 6c9826f..6c13eb5 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -102,7 +102,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
102 sceneObject.AddPart(part); 102 sceneObject.AddPart(part);
103 part.LinkNum = linkNum; 103 part.LinkNum = linkNum;
104 part.TrimPermissions(); 104 part.TrimPermissions();
105 part.StoreUndoState(); 105 part.StoreUndoState(UndoType.STATE_ALL);
106 reader.Close(); 106 reader.Close();
107 sr.Close(); 107 sr.Close();
108 } 108 }
@@ -220,7 +220,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
220 if (originalLinkNum != 0) 220 if (originalLinkNum != 0)
221 part.LinkNum = originalLinkNum; 221 part.LinkNum = originalLinkNum;
222 222
223 part.StoreUndoState(); 223 part.StoreUndoState(UndoType.STATE_ALL);
224 reader.Close(); 224 reader.Close();
225 sr.Close(); 225 sr.Close();
226 } 226 }
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 55e407e..f71b507 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -27,48 +27,125 @@
27 27
28using OpenMetaverse; 28using OpenMetaverse;
29using OpenSim.Region.Framework.Interfaces; 29using OpenSim.Region.Framework.Interfaces;
30using System;
30 31
31namespace OpenSim.Region.Framework.Scenes 32namespace OpenSim.Region.Framework.Scenes
32{ 33{
34 [Flags]
35 public enum UndoType
36 {
37 STATE_PRIM_POSITION = 1,
38 STATE_PRIM_ROTATION = 2,
39 STATE_PRIM_SCALE = 4,
40 STATE_PRIM_ALL = 7,
41 STATE_GROUP_POSITION = 8,
42 STATE_GROUP_ROTATION = 16,
43 STATE_GROUP_SCALE = 32,
44 STATE_GROUP_ALL = 56,
45 STATE_ALL = 63
46 }
47
33 public class UndoState 48 public class UndoState
34 { 49 {
35 public Vector3 Position = Vector3.Zero; 50 public Vector3 Position = Vector3.Zero;
36 public Vector3 Scale = Vector3.Zero; 51 public Vector3 Scale = Vector3.Zero;
37 public Quaternion Rotation = Quaternion.Identity; 52 public Quaternion Rotation = Quaternion.Identity;
53 public Vector3 GroupPosition = Vector3.Zero;
54 public Quaternion GroupRotation = Quaternion.Identity;
55 public Vector3 GroupScale = Vector3.Zero;
56 public DateTime LastUpdated = DateTime.Now;
57 public UndoType Type;
38 58
39 public UndoState(SceneObjectPart part) 59 public UndoState(SceneObjectPart part, UndoType type)
40 { 60 {
61 Type = type;
41 if (part != null) 62 if (part != null)
42 { 63 {
43 if (part.ParentID == 0) 64 if (part.ParentID == 0)
44 { 65 {
45 Position = part.ParentGroup.AbsolutePosition; 66 GroupScale = part.ParentGroup.RootPart.Shape.Scale;
67
68 //FUBAR WARNING: Do NOT get the group's absoluteposition here
69 //or you'll experience a loop and/or a stack issue
70 GroupPosition = part.ParentGroup.RootPart.AbsolutePosition;
71 GroupRotation = part.ParentGroup.GroupRotation;
72 Position = part.ParentGroup.RootPart.AbsolutePosition;
46 Rotation = part.RotationOffset; 73 Rotation = part.RotationOffset;
47 Scale = part.Shape.Scale; 74 Scale = part.Shape.Scale;
75 LastUpdated = DateTime.Now;
48 } 76 }
49 else 77 else
50 { 78 {
79 GroupScale = part.Shape.Scale;
80
81 //FUBAR WARNING: Do NOT get the group's absoluteposition here
82 //or you'll experience a loop and/or a stack issue
83 GroupPosition = part.ParentGroup.RootPart.AbsolutePosition;
84 GroupRotation = part.ParentGroup.Rotation;
51 Position = part.OffsetPosition; 85 Position = part.OffsetPosition;
52 Rotation = part.RotationOffset; 86 Rotation = part.RotationOffset;
53 Scale = part.Shape.Scale; 87 Scale = part.Shape.Scale;
88 LastUpdated = DateTime.Now;
54 } 89 }
55 } 90 }
56 } 91 }
57 92 public void Merge(UndoState last)
93 {
94 if ((Type & UndoType.STATE_GROUP_POSITION) == 0 || ((last.Type & UndoType.STATE_GROUP_POSITION) >= (Type & UndoType.STATE_GROUP_POSITION)))
95 {
96 GroupPosition = last.GroupPosition;
97 Position = last.Position;
98 }
99 if ((Type & UndoType.STATE_GROUP_SCALE) == 0 || ((last.Type & UndoType.STATE_GROUP_SCALE) >= (Type & UndoType.STATE_GROUP_SCALE)))
100 {
101 GroupScale = last.GroupScale;
102 Scale = last.Scale;
103 }
104 if ((Type & UndoType.STATE_GROUP_ROTATION) == 0 || ((last.Type & UndoType.STATE_GROUP_ROTATION) >= (Type & UndoType.STATE_GROUP_ROTATION)))
105 {
106 GroupRotation = last.GroupRotation;
107 Rotation = last.Rotation;
108 }
109 if ((Type & UndoType.STATE_PRIM_POSITION) == 0 || ((last.Type & UndoType.STATE_PRIM_POSITION) >= (Type & UndoType.STATE_PRIM_POSITION)))
110 {
111 Position = last.Position;
112 }
113 if ((Type & UndoType.STATE_PRIM_SCALE) == 0 || ((last.Type & UndoType.STATE_PRIM_SCALE) >= (Type & UndoType.STATE_PRIM_SCALE)))
114 {
115 Scale = last.Scale;
116 }
117 if ((Type & UndoType.STATE_PRIM_ROTATION) == 0 || ((last.Type & UndoType.STATE_PRIM_ROTATION) >= (Type & UndoType.STATE_PRIM_ROTATION)))
118 {
119 Rotation = last.Rotation;
120 }
121 Type = Type | last.Type;
122 }
123 public bool Compare(UndoState undo)
124 {
125 if (undo == null || Position == null) return false;
126 if (undo.Position == Position && undo.Rotation == Rotation && undo.Scale == Scale && undo.GroupPosition == GroupPosition && undo.GroupScale == GroupScale && undo.GroupRotation == GroupRotation)
127 {
128 return true;
129 }
130 else
131 {
132 return false;
133 }
134 }
58 public bool Compare(SceneObjectPart part) 135 public bool Compare(SceneObjectPart part)
59 { 136 {
60 if (part != null) 137 if (part != null)
61 { 138 {
62 if (part.ParentID == 0) 139 if (part.ParentID == 0)
63 { 140 {
64 if (Position == part.ParentGroup.AbsolutePosition && Rotation == part.ParentGroup.Rotation) 141 if (Position == part.ParentGroup.RootPart.AbsolutePosition && Rotation == part.ParentGroup.Rotation && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale)
65 return true; 142 return true;
66 else 143 else
67 return false; 144 return false;
68 } 145 }
69 else 146 else
70 { 147 {
71 if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale) 148 if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale)
72 return true; 149 return true;
73 else 150 else
74 return false; 151 return false;
@@ -78,62 +155,70 @@ namespace OpenSim.Region.Framework.Scenes
78 return false; 155 return false;
79 } 156 }
80 157
81 public void PlaybackState(SceneObjectPart part) 158 private void RestoreState(SceneObjectPart part)
82 { 159 {
160 bool GroupChange = false;
161 if ((Type & UndoType.STATE_GROUP_POSITION) != 0
162 || (Type & UndoType.STATE_GROUP_ROTATION) != 0
163 || (Type & UndoType.STATE_GROUP_SCALE) != 0)
164 {
165 GroupChange = true;
166 }
167
83 if (part != null) 168 if (part != null)
84 { 169 {
85 part.Undoing = true; 170 part.Undoing = true;
86 171
87 if (part.ParentID == 0) 172 if (part.ParentID == 0 && GroupChange == false)
88 { 173 {
89 if (Position != Vector3.Zero) 174 if (Position != Vector3.Zero)
90 part.ParentGroup.AbsolutePosition = Position; 175
91 part.RotationOffset = Rotation; 176 part.ParentGroup.UpdateSinglePosition(Position, part.LocalId);
177 part.ParentGroup.UpdateSingleRotation(Rotation, part.LocalId);
92 if (Scale != Vector3.Zero) 178 if (Scale != Vector3.Zero)
93 part.Resize(Scale); 179 part.Resize(Scale);
94 part.ParentGroup.ScheduleGroupForTerseUpdate(); 180 part.ParentGroup.ScheduleGroupForTerseUpdate();
95 } 181 }
96 else 182 else
97 { 183 {
98 if (Position != Vector3.Zero) 184 if (GroupChange)
99 part.OffsetPosition = Position; 185 {
100 part.UpdateRotation(Rotation); 186 part.ParentGroup.RootPart.Undoing = true;
101 if (Scale != Vector3.Zero) 187 if (GroupPosition != Vector3.Zero)
102 part.Resize(Scale); part.ScheduleTerseUpdate(); 188 {
189 //Calculate the scale...
190 Vector3 gs = part.Shape.Scale;
191 float scale = GroupScale.Z / gs.Z;
192
193 //Scale first since it can affect our position
194 part.ParentGroup.GroupResize(gs * scale, part.LocalId);
195 part.ParentGroup.AbsolutePosition = GroupPosition;
196 part.ParentGroup.UpdateGroupRotationR(GroupRotation);
197
198 }
199 part.ParentGroup.RootPart.Undoing = false;
200 }
201 else
202 {
203 if (Position != Vector3.Zero) //We can use this for all the updates since all are set
204 {
205 part.OffsetPosition = Position;
206 part.UpdateRotation(Rotation);
207 part.Resize(Scale); part.ScheduleTerseUpdate();
208 }
209 }
103 } 210 }
104 part.Undoing = false; 211 part.Undoing = false;
105 212
106 } 213 }
107 } 214 }
215 public void PlaybackState(SceneObjectPart part)
216 {
217 RestoreState(part);
218 }
108 public void PlayfwdState(SceneObjectPart part) 219 public void PlayfwdState(SceneObjectPart part)
109 { 220 {
110 if (part != null) 221 RestoreState(part);
111 {
112 part.Undoing = true;
113
114 if (part.ParentID == 0)
115 {
116 if (Position != Vector3.Zero)
117 part.ParentGroup.AbsolutePosition = Position;
118 if (Rotation != Quaternion.Identity)
119 part.UpdateRotation(Rotation);
120 if (Scale != Vector3.Zero)
121 part.Resize(Scale);
122 part.ParentGroup.ScheduleGroupForTerseUpdate();
123 }
124 else
125 {
126 if (Position != Vector3.Zero)
127 part.OffsetPosition = Position;
128 if (Rotation != Quaternion.Identity)
129 part.UpdateRotation(Rotation);
130 if (Scale != Vector3.Zero)
131 part.Resize(Scale);
132 part.ScheduleTerseUpdate();
133 }
134 part.Undoing = false;
135
136 }
137 } 222 }
138 } 223 }
139 public class LandUndoState 224 public class LandUndoState
@@ -161,3 +246,4 @@ namespace OpenSim.Region.Framework.Scenes
161 } 246 }
162 } 247 }
163} 248}
249