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.cs226
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs355
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs453
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs224
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs559
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs228
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs794
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs880
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs87
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
20 files changed, 2928 insertions, 1021 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index e07d8b4..4925175 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -57,11 +57,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
57 { 57 {
58 get { return m_movementAnimation; } 58 get { return m_movementAnimation; }
59 } 59 }
60 protected string m_movementAnimation = "DEFAULT"; 60 // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist!
61 61 protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init.
62 private int m_animTickFall; 62 private int m_animTickFall;
63 private int m_animTickJump; 63// private int m_animTickJump;
64 64 public int m_animTickJump; // ScenePresence has to see this to control +Z force
65 public bool m_jumping = false; // Add for jumping
66 public float m_jumpVelocity = 0f; // Add for jumping
67 private int m_landing = 0; // Add for jumping
68 public bool m_falling = false; // Add for falling
69 private float m_fallHeight; // Add for falling
70
65 /// <value> 71 /// <value>
66 /// The scene presence that this animator applies to 72 /// The scene presence that this animator applies to
67 /// </value> 73 /// </value>
@@ -122,7 +128,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation
122 128
123 public void ResetAnimations() 129 public void ResetAnimations()
124 { 130 {
131Console.WriteLine("ResetA.............");
125 m_animations.Clear(); 132 m_animations.Clear();
133TrySetMovementAnimation("STAND");
126 } 134 }
127 135
128 /// <summary> 136 /// <summary>
@@ -152,14 +160,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
152 /// </summary> 160 /// </summary>
153 public string GetMovementAnimation() 161 public string GetMovementAnimation()
154 { 162 {
155 const float FALL_DELAY = 0.33f; 163//Console.WriteLine("GMA-------"); //##
156 const float PREJUMP_DELAY = 0.25f; 164//#@ const float FALL_DELAY = 0.33f;
157 165 const float FALL_DELAY = 800f; //## mS
166//rm for jumping const float PREJUMP_DELAY = 0.25f;
167 const float PREJUMP_DELAY = 200f; // mS add for jumping
168 const float JUMP_PERIOD = 800f; // mS add for jumping
158 #region Inputs 169 #region Inputs
159 if (m_scenePresence.SitGround) 170
160 {
161 return "SIT_GROUND_CONSTRAINED";
162 }
163 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 171 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
164 PhysicsActor actor = m_scenePresence.PhysicsActor; 172 PhysicsActor actor = m_scenePresence.PhysicsActor;
165 173
@@ -169,11 +177,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
169 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 177 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
170 178
171 // Check control flags 179 // Check control flags
172 bool heldForward = 180 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);
173 (((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)); 181 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);
174 bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; 182 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);
175 bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; 183 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);
176 bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
177 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 184 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
178 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 185 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
179 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 186 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -192,8 +199,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
192 199
193 // Is the avatar trying to move? 200 // Is the avatar trying to move?
194// bool moving = (move != Vector3.Zero); 201// bool moving = (move != Vector3.Zero);
195 bool jumping = m_animTickJump != 0; 202// rm for jumping bool jumping = m_animTickJump != 0;
196
197 #endregion Inputs 203 #endregion Inputs
198 204
199 #region Flying 205 #region Flying
@@ -202,6 +208,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
202 { 208 {
203 m_animTickFall = 0; 209 m_animTickFall = 0;
204 m_animTickJump = 0; 210 m_animTickJump = 0;
211 m_jumping = false; //add for jumping
212 m_falling = true; //add for falling
213 m_jumpVelocity = 0f; //add for jumping
214 actor.Selected = false; //add for jumping flag
215 m_fallHeight = actor.Position.Z; // save latest flying height
205 216
206 if (move.X != 0f || move.Y != 0f) 217 if (move.X != 0f || move.Y != 0f)
207 { 218 {
@@ -213,8 +224,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
213 } 224 }
214 else if (move.Z < 0f) 225 else if (move.Z < 0f)
215 { 226 {
216 if (actor != null && actor.IsColliding) 227 if (actor != null && actor.IsColliding)
228 { //##
229//Console.WriteLine("LAND FLYING"); // ##
217 return "LAND"; 230 return "LAND";
231 } //#
218 else 232 else
219 return "HOVER_DOWN"; 233 return "HOVER_DOWN";
220 } 234 }
@@ -228,48 +242,127 @@ namespace OpenSim.Region.Framework.Scenes.Animation
228 242
229 #region Falling/Floating/Landing 243 #region Falling/Floating/Landing
230 244
231 if (actor == null || !actor.IsColliding) 245// rm for jumping if (actor == null || !actor.IsColliding)
246 if ((actor == null || !actor.IsColliding) && !m_jumping) // add for jumping
232 { 247 {
233 float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 248// rm float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
249 float fallElapsed = (float)(Environment.TickCount - m_animTickFall); // add, in mS
234 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; 250 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
251//Console.WriteLine("falling t={0} v={1}", fallElapsed, fallVelocity); //##
235 252
236 if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f)) 253// rm for fall if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f))
254 if (!m_jumping && (fallVelocity < -3.0f) ) m_falling = true; // add for falling and jumping
255
256 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) // add for jumping
257 // not falling yet or going up
237 { 258 {
238 // Just started falling 259 // reset start of fall time
239 m_animTickFall = Environment.TickCount; 260 m_animTickFall = Environment.TickCount;
240 } 261 }
241 else if (!jumping && fallElapsed > FALL_DELAY) 262// else if (!jumping && fallElapsed > FALL_DELAY)
263 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.m_wasFlying)) // add for falling and jumping
242 { 264 {
243 // Falling long enough to trigger the animation 265 // Falling long enough to trigger the animation
266//Console.WriteLine("FALLDOWN"); //##
244 return "FALLDOWN"; 267 return "FALLDOWN";
245 } 268 }
246 else if (m_animTickJump == -1)
247 {
248 m_animTickJump = 0;
249 return "STAND";
250 }
251 269
252 return m_movementAnimation; 270 return m_movementAnimation;
253 } 271 }
254 272
255 #endregion Falling/Floating/Landing 273 #endregion Falling/Floating/Landing
256 274
275
276 #region Jumping // section added for jumping...
277
278 int jumptime;
279 jumptime = Environment.TickCount - m_animTickJump;
280
281
282 if ((move.Z > 0f) && (!m_jumping))
283 {
284//Console.WriteLine("PJ {0}", jumptime); //##
285 // Start jumping, prejump
286 m_animTickFall = 0;
287 m_jumping = true;
288 m_falling = false;
289 actor.Selected = true; // borrowed for jmping flag
290 m_animTickJump = Environment.TickCount;
291 m_jumpVelocity = 0.35f;
292 return "PREJUMP";
293 }
294
295 if(m_jumping)
296 {
297 if ( (jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
298 {
299//Console.WriteLine("LA {0}", jumptime); //##
300 // end jumping
301 m_jumping = false;
302 m_falling = false;
303 actor.Selected = false; // borrowed for jumping flag
304 m_jumpVelocity = 0f;
305 m_animTickFall = Environment.TickCount;
306 return "LAND";
307 }
308 else if (jumptime > JUMP_PERIOD)
309 {
310//Console.WriteLine("JD {0}", jumptime); //##
311 // jump down
312 m_jumpVelocity = 0f;
313 return "JUMP";
314 }
315 else if (jumptime > PREJUMP_DELAY)
316 {
317//Console.WriteLine("JU {0}", jumptime); //##
318 // jump up
319 m_jumping = true;
320 m_jumpVelocity = 10f;
321 return "JUMP";
322 }
323 }
324
325 #endregion Jumping // end added section
326
257 #region Ground Movement 327 #region Ground Movement
258 328
259 if (m_movementAnimation == "FALLDOWN") 329 if (m_movementAnimation == "FALLDOWN")
260 { 330 {
331 m_falling = false;
261 m_animTickFall = Environment.TickCount; 332 m_animTickFall = Environment.TickCount;
262
263 // TODO: SOFT_LAND support 333 // TODO: SOFT_LAND support
264 return "LAND"; 334 float fallHeight = m_fallHeight - actor.Position.Z;
335//Console.WriteLine("Hit from {0}", fallHeight); //##
336 if (fallHeight > 15.0f) // add for falling
337 return "STANDUP";
338 else if (fallHeight > 8.0f) // add for falling
339 return "SOFT_LAND"; // add for falling
340 else // add for falling
341 return "LAND"; // add for falling
265 } 342 }
266 else if (m_movementAnimation == "LAND") 343// rm jumping float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
344// rm jumping if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY))
345// rm for landing return "LAND";
346 else if ((m_movementAnimation == "LAND") || (m_movementAnimation == "SOFT_LAND") || (m_movementAnimation == "STANDUP"))
267 { 347 {
268 float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 348 int landElapsed = Environment.TickCount - m_animTickFall; // add for jumping
269 if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) 349 int limit = 1000; // add for jumping
270 return "LAND"; 350 if(m_movementAnimation == "LAND") limit = 350; // add for jumping
271 } 351 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
272 352
353 if ((m_animTickFall != 0) && (landElapsed <= limit)) // add for jumping
354 {
355//Console.WriteLine("Lelapse {0}", m_movementAnimation); //##
356 return m_movementAnimation;
357 }
358 else
359 {
360//Console.WriteLine("end/STAND"); //##
361 m_fallHeight = actor.Position.Z; // save latest flying height
362 return "STAND";
363 }
364 }
365/* This section removed, replaced by jumping section
273 m_animTickFall = 0; 366 m_animTickFall = 0;
274 367
275 if (move.Z > 0.2f) 368 if (move.Z > 0.2f)
@@ -281,7 +374,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
281 m_animTickJump = Environment.TickCount; 374 m_animTickJump = Environment.TickCount;
282 return "PREJUMP"; 375 return "PREJUMP";
283 } 376 }
284 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) 377 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 800.0f)
285 { 378 {
286 // Start actual jump 379 // Start actual jump
287 if (m_animTickJump == -1) 380 if (m_animTickJump == -1)
@@ -294,37 +387,40 @@ namespace OpenSim.Region.Framework.Scenes.Animation
294 m_animTickJump = -1; 387 m_animTickJump = -1;
295 return "JUMP"; 388 return "JUMP";
296 } 389 }
297 else
298 return "JUMP";
299 } 390 }
300 else 391 else
301 { 392 {
302 // Not jumping 393 // Not jumping
303 m_animTickJump = 0; 394 m_animTickJump = 0;
304 395 */
305 if (move.X != 0f || move.Y != 0f) 396 // next section moved outside paren. and realigned for jumping
306 { 397 if (move.X != 0f || move.Y != 0f)
307 // Walking / crouchwalking / running 398 {
308 if (move.Z < 0) 399 m_fallHeight = actor.Position.Z; // save latest flying height
309 return "CROUCHWALK"; 400 m_falling = false; // Add for falling
310 else if (m_scenePresence.SetAlwaysRun) 401 // Walking / crouchwalking / running
311 return "RUN"; 402 if (move.Z < 0f)
312 else 403 return "CROUCHWALK";
313 return "WALK"; 404 else if (m_scenePresence.SetAlwaysRun)
314 } 405 return "RUN";
315 else 406 else
316 { 407 return "WALK";
317 // Not walking
318 if (move.Z < 0)
319 return "CROUCH";
320 else
321 return "STAND";
322 }
323 } 408 }
324 409// rm for jumping else
410 else if (!m_jumping) // add for jumping
411 {
412 m_falling = false; // Add for falling
413 // Not walking
414 if (move.Z < 0f)
415 return "CROUCH";
416 else
417 return "STAND";
418 }
419 // end section realign for jumping
325 #endregion Ground Movement 420 #endregion Ground Movement
326 421
327 //return m_movementAnimation; 422 m_falling = false; // Add for falling
423 return m_movementAnimation;
328 } 424 }
329 425
330 /// <summary> 426 /// <summary>
@@ -333,9 +429,15 @@ namespace OpenSim.Region.Framework.Scenes.Animation
333 public void UpdateMovementAnimations() 429 public void UpdateMovementAnimations()
334 { 430 {
335 m_movementAnimation = GetMovementAnimation(); 431 m_movementAnimation = GetMovementAnimation();
336// m_log.DebugFormat( 432/* if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
337// "[SCENE PRESENCE ANIMATOR]: Got animation {0} for {1}", m_movementAnimation, m_scenePresence.Name); 433 {
338 TrySetMovementAnimation(m_movementAnimation); 434 // This was the previous behavior before PREJUMP
435 TrySetMovementAnimation("JUMP");
436 }
437 else
438 { removed for jumping */
439 TrySetMovementAnimation(m_movementAnimation);
440// rm for jumping }
339 } 441 }
340 442
341 public UUID[] GetAnimationArray() 443 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 3423542..088839d 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
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 96da2c3..65c6a29 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;
@@ -775,6 +779,26 @@ namespace OpenSim.Region.Framework.Scenes
775 } 779 }
776 } 780 }
777 } 781 }
782 public void TriggerTerrainUpdate()
783 {
784 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
785 if (handlerTerrainUpdate != null)
786 {
787 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
788 {
789 try
790 {
791 d();
792 }
793 catch (Exception e)
794 {
795 m_log.ErrorFormat(
796 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
797 e.Message, e.StackTrace);
798 }
799 }
800 }
801 }
778 802
779 public void TriggerTerrainTick() 803 public void TriggerTerrainTick()
780 { 804 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 1b10e3c..0a34a4c 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -157,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
157 157
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 159 {
160 uint pqueue = ComputeDistancePriority(client,entity,true); 160 uint pqueue = ComputeDistancePriority(client,entity,false);
161 161
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 163 if (presence != null)
@@ -226,7 +226,7 @@ namespace OpenSim.Region.Framework.Scenes
226 226
227 for (int i = 0; i < queues - 1; i++) 227 for (int i = 0; i < queues - 1; i++)
228 { 228 {
229 if (distance < 10 * Math.Pow(2.0,i)) 229 if (distance < 30 * Math.Pow(2.0,i))
230 break; 230 break;
231 pqueue++; 231 pqueue++;
232 } 232 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 663aa22..53f0f2e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -124,34 +124,22 @@ namespace OpenSim.Region.Framework.Scenes
124 /// <param name="item"></param> 124 /// <param name="item"></param>
125 public bool AddInventoryItem(InventoryItemBase item) 125 public bool AddInventoryItem(InventoryItemBase item)
126 { 126 {
127 if (UUID.Zero == item.Folder) 127 InventoryFolderBase folder;
128
129 if (item.Folder == UUID.Zero)
128 { 130 {
129 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 131 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
130 if (f != null) 132 if (folder == null)
131 { 133 {
132// m_log.DebugFormat( 134 folder = InventoryService.GetRootFolder(item.Owner);
133// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", 135
134// f.Name, (AssetType)f.Type, item.Name); 136 if (folder == null)
135
136 item.Folder = f.ID;
137 }
138 else
139 {
140 f = InventoryService.GetRootFolder(item.Owner);
141 if (f != null)
142 {
143 item.Folder = f.ID;
144 }
145 else
146 {
147 m_log.WarnFormat(
148 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
149 item.Owner, item.Name);
150 return false; 137 return false;
151 }
152 } 138 }
139
140 item.Folder = folder.ID;
153 } 141 }
154 142
155 if (InventoryService.AddItem(item)) 143 if (InventoryService.AddItem(item))
156 { 144 {
157 int userlevel = 0; 145 int userlevel = 0;
@@ -271,8 +259,7 @@ namespace OpenSim.Region.Framework.Scenes
271 259
272 // Update item with new asset 260 // Update item with new asset
273 item.AssetID = asset.FullID; 261 item.AssetID = asset.FullID;
274 if (group.UpdateInventoryItem(item)) 262 group.UpdateInventoryItem(item);
275 remoteClient.SendAgentAlertMessage("Script saved", false);
276 263
277 part.SendPropertiesToClient(remoteClient); 264 part.SendPropertiesToClient(remoteClient);
278 265
@@ -283,12 +270,7 @@ namespace OpenSim.Region.Framework.Scenes
283 { 270 {
284 // Needs to determine which engine was running it and use that 271 // Needs to determine which engine was running it and use that
285 // 272 //
286 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 273 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
287 errors = part.Inventory.GetScriptErrors(item.ItemID);
288 }
289 else
290 {
291 remoteClient.SendAgentAlertMessage("Script saved", false);
292 } 274 }
293 part.ParentGroup.ResumeScripts(); 275 part.ParentGroup.ResumeScripts();
294 return errors; 276 return errors;
@@ -351,6 +333,7 @@ namespace OpenSim.Region.Framework.Scenes
351 { 333 {
352 if (UUID.Zero == transactionID) 334 if (UUID.Zero == transactionID)
353 { 335 {
336 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
354 item.Name = itemUpd.Name; 337 item.Name = itemUpd.Name;
355 item.Description = itemUpd.Description; 338 item.Description = itemUpd.Description;
356 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 339 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -728,6 +711,8 @@ namespace OpenSim.Region.Framework.Scenes
728 return; 711 return;
729 } 712 }
730 713
714 if (newName == null) newName = item.Name;
715
731 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 716 AssetBase asset = AssetService.Get(item.AssetID.ToString());
732 717
733 if (asset != null) 718 if (asset != null)
@@ -784,6 +769,24 @@ namespace OpenSim.Region.Framework.Scenes
784 } 769 }
785 770
786 /// <summary> 771 /// <summary>
772 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
773 /// </summary>
774 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
775 {
776 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
777 foreach (InventoryItemBase b in items)
778 {
779 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
780 InventoryItemBase n = InventoryService.GetItem(b);
781 n.Folder = destfolder;
782 moveitems.Add(n);
783 remoteClient.SendInventoryItemCreateUpdate(n, 0);
784 }
785
786 MoveInventoryItem(remoteClient, moveitems);
787 }
788
789 /// <summary>
787 /// Move an item within the agent's inventory. 790 /// Move an item within the agent's inventory.
788 /// </summary> 791 /// </summary>
789 /// <param name="remoteClient"></param> 792 /// <param name="remoteClient"></param>
@@ -984,25 +987,29 @@ namespace OpenSim.Region.Framework.Scenes
984 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 987 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
985 { 988 {
986 SceneObjectPart part = GetSceneObjectPart(localID); 989 SceneObjectPart part = GetSceneObjectPart(localID);
987 if (part == null) 990 SceneObjectGroup group = null;
988 return; 991 if (part != null)
992 {
993 group = part.ParentGroup;
994 }
995 if (part != null && group != null)
996 {
997 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
998 return;
989 999
990 SceneObjectGroup group = part.ParentGroup; 1000 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
991 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 1001 if (item == null)
992 return; 1002 return;
993
994 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
995 if (item == null)
996 return;
997 1003
998 if (item.Type == 10) 1004 if (item.Type == 10)
999 { 1005 {
1000 part.RemoveScriptEvents(itemID); 1006 part.RemoveScriptEvents(itemID);
1001 EventManager.TriggerRemoveScript(localID, itemID); 1007 EventManager.TriggerRemoveScript(localID, itemID);
1008 }
1009
1010 group.RemoveInventoryItem(localID, itemID);
1011 part.SendPropertiesToClient(remoteClient);
1002 } 1012 }
1003
1004 group.RemoveInventoryItem(localID, itemID);
1005 part.SendPropertiesToClient(remoteClient);
1006 } 1013 }
1007 1014
1008 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) 1015 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId)
@@ -1213,6 +1220,10 @@ namespace OpenSim.Region.Framework.Scenes
1213 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1220 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1214 return; 1221 return;
1215 1222
1223 bool overrideNoMod = false;
1224 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1225 overrideNoMod = true;
1226
1216 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1227 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1217 { 1228 {
1218 // object cannot copy items to an object owned by a different owner 1229 // object cannot copy items to an object owned by a different owner
@@ -1222,7 +1233,7 @@ namespace OpenSim.Region.Framework.Scenes
1222 } 1233 }
1223 1234
1224 // must have both move and modify permission to put an item in an object 1235 // must have both move and modify permission to put an item in an object
1225 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1236 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1226 { 1237 {
1227 return; 1238 return;
1228 } 1239 }
@@ -1281,6 +1292,14 @@ namespace OpenSim.Region.Framework.Scenes
1281 1292
1282 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1293 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1283 { 1294 {
1295 SceneObjectPart destPart = GetSceneObjectPart(destID);
1296 if (destPart != null) // Move into a prim
1297 {
1298 foreach(UUID itemID in items)
1299 MoveTaskInventoryItem(destID, host, itemID);
1300 return destID; // Prim folder ID == prim ID
1301 }
1302
1284 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1303 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1285 1304
1286 UUID newFolderID = UUID.Random(); 1305 UUID newFolderID = UUID.Random();
@@ -1460,13 +1479,6 @@ namespace OpenSim.Region.Framework.Scenes
1460 { 1479 {
1461 agentTransactions.HandleTaskItemUpdateFromTransaction( 1480 agentTransactions.HandleTaskItemUpdateFromTransaction(
1462 remoteClient, part, transactionID, currentItem); 1481 remoteClient, part, transactionID, currentItem);
1463
1464 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1465 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1466 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1467 remoteClient.SendAgentAlertMessage("Script saved", false);
1468 else
1469 remoteClient.SendAgentAlertMessage("Item saved", false);
1470 } 1482 }
1471 1483
1472 // Base ALWAYS has move 1484 // Base ALWAYS has move
@@ -1607,7 +1619,7 @@ namespace OpenSim.Region.Framework.Scenes
1607 return; 1619 return;
1608 1620
1609 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1621 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1610 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1622 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1611 remoteClient.AgentId); 1623 remoteClient.AgentId);
1612 AssetService.Store(asset); 1624 AssetService.Store(asset);
1613 1625
@@ -1760,23 +1772,32 @@ namespace OpenSim.Region.Framework.Scenes
1760 // build a list of eligible objects 1772 // build a list of eligible objects
1761 List<uint> deleteIDs = new List<uint>(); 1773 List<uint> deleteIDs = new List<uint>();
1762 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1774 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1763 1775 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1764 // Start with true for both, then remove the flags if objects
1765 // that we can't derez are part of the selection
1766 bool permissionToTake = true;
1767 bool permissionToTakeCopy = true;
1768 bool permissionToDelete = true;
1769 1776
1770 foreach (uint localID in localIDs) 1777 foreach (uint localID in localIDs)
1771 { 1778 {
1779 // Start with true for both, then remove the flags if objects
1780 // that we can't derez are part of the selection
1781 bool permissionToTake = true;
1782 bool permissionToTakeCopy = true;
1783 bool permissionToDelete = true;
1784
1772 // Invalid id 1785 // Invalid id
1773 SceneObjectPart part = GetSceneObjectPart(localID); 1786 SceneObjectPart part = GetSceneObjectPart(localID);
1774 if (part == null) 1787 if (part == null)
1788 {
1789 //Client still thinks the object exists, kill it
1790 deleteIDs.Add(localID);
1775 continue; 1791 continue;
1792 }
1776 1793
1777 // Already deleted by someone else 1794 // Already deleted by someone else
1778 if (part.ParentGroup.IsDeleted) 1795 if (part.ParentGroup.IsDeleted)
1796 {
1797 //Client still thinks the object exists, kill it
1798 deleteIDs.Add(localID);
1779 continue; 1799 continue;
1800 }
1780 1801
1781 // Can't delete child prims 1802 // Can't delete child prims
1782 if (part != part.ParentGroup.RootPart) 1803 if (part != part.ParentGroup.RootPart)
@@ -1784,9 +1805,6 @@ namespace OpenSim.Region.Framework.Scenes
1784 1805
1785 SceneObjectGroup grp = part.ParentGroup; 1806 SceneObjectGroup grp = part.ParentGroup;
1786 1807
1787 deleteIDs.Add(localID);
1788 deleteGroups.Add(grp);
1789
1790 if (remoteClient == null) 1808 if (remoteClient == null)
1791 { 1809 {
1792 // Autoreturn has a null client. Nothing else does. So 1810 // Autoreturn has a null client. Nothing else does. So
@@ -1803,81 +1821,193 @@ namespace OpenSim.Region.Framework.Scenes
1803 } 1821 }
1804 else 1822 else
1805 { 1823 {
1806 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1824 if (action == DeRezAction.TakeCopy)
1825 {
1826 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1827 permissionToTakeCopy = false;
1828 }
1829 else
1830 {
1807 permissionToTakeCopy = false; 1831 permissionToTakeCopy = false;
1808 1832 }
1809 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1833 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1810 permissionToTake = false; 1834 permissionToTake = false;
1811 1835
1812 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1836 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1813 permissionToDelete = false; 1837 permissionToDelete = false;
1814 } 1838 }
1815 }
1816 1839
1817 // Handle god perms 1840 // Handle god perms
1818 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1841 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1819 { 1842 {
1820 permissionToTake = true; 1843 permissionToTake = true;
1821 permissionToTakeCopy = true; 1844 permissionToTakeCopy = true;
1822 permissionToDelete = true; 1845 permissionToDelete = true;
1823 } 1846 }
1824 1847
1825 // If we're re-saving, we don't even want to delete 1848 // If we're re-saving, we don't even want to delete
1826 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1849 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1827 permissionToDelete = false; 1850 permissionToDelete = false;
1828 1851
1829 // if we want to take a copy, we also don't want to delete 1852 // if we want to take a copy, we also don't want to delete
1830 // Note: after this point, the permissionToTakeCopy flag 1853 // Note: after this point, the permissionToTakeCopy flag
1831 // becomes irrelevant. It already includes the permissionToTake 1854 // becomes irrelevant. It already includes the permissionToTake
1832 // permission and after excluding no copy items here, we can 1855 // permission and after excluding no copy items here, we can
1833 // just use that. 1856 // just use that.
1834 if (action == DeRezAction.TakeCopy) 1857 if (action == DeRezAction.TakeCopy)
1835 { 1858 {
1836 // If we don't have permission, stop right here 1859 // If we don't have permission, stop right here
1837 if (!permissionToTakeCopy) 1860 if (!permissionToTakeCopy)
1838 return; 1861 return;
1839 1862
1840 permissionToTake = true; 1863 permissionToTake = true;
1841 // Don't delete 1864 // Don't delete
1842 permissionToDelete = false; 1865 permissionToDelete = false;
1843 } 1866 }
1844 1867
1845 if (action == DeRezAction.Return) 1868 if (action == DeRezAction.Return)
1846 {
1847 if (remoteClient != null)
1848 { 1869 {
1849 if (Permissions.CanReturnObjects( 1870 if (remoteClient != null)
1850 null,
1851 remoteClient.AgentId,
1852 deleteGroups))
1853 { 1871 {
1854 permissionToTake = true; 1872 if (Permissions.CanReturnObjects(
1855 permissionToDelete = true; 1873 null,
1856 1874 remoteClient.AgentId,
1857 foreach (SceneObjectGroup g in deleteGroups) 1875 deleteGroups))
1858 { 1876 {
1859 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1877 permissionToTake = true;
1878 permissionToDelete = true;
1879
1880 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1860 } 1881 }
1861 } 1882 }
1883 else // Auto return passes through here with null agent
1884 {
1885 permissionToTake = true;
1886 permissionToDelete = true;
1887 }
1862 } 1888 }
1863 else // Auto return passes through here with null agent 1889
1890 if (permissionToTake && (!permissionToDelete))
1891 takeGroups.Add(grp);
1892
1893 if (permissionToDelete)
1864 { 1894 {
1865 permissionToTake = true; 1895 if (permissionToTake)
1866 permissionToDelete = true; 1896 deleteGroups.Add(grp);
1897 deleteIDs.Add(grp.LocalId);
1867 } 1898 }
1868 } 1899 }
1869 1900
1870 if (permissionToTake) 1901 SendKillObject(deleteIDs);
1902
1903 if (deleteGroups.Count > 0)
1871 { 1904 {
1905 foreach (SceneObjectGroup g in deleteGroups)
1906 deleteIDs.Remove(g.LocalId);
1907
1872 m_asyncSceneObjectDeleter.DeleteToInventory( 1908 m_asyncSceneObjectDeleter.DeleteToInventory(
1873 action, destinationID, deleteGroups, remoteClient, 1909 action, destinationID, deleteGroups, remoteClient,
1874 permissionToDelete); 1910 true);
1875 } 1911 }
1876 else if (permissionToDelete) 1912 if (takeGroups.Count > 0)
1913 {
1914 m_asyncSceneObjectDeleter.DeleteToInventory(
1915 action, destinationID, takeGroups, remoteClient,
1916 false);
1917 }
1918 if (deleteIDs.Count > 0)
1877 { 1919 {
1878 foreach (SceneObjectGroup g in deleteGroups) 1920 foreach (SceneObjectGroup g in deleteGroups)
1879 DeleteSceneObject(g, false); 1921 DeleteSceneObject(g, true);
1922 }
1923 }
1924
1925 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
1926 {
1927 itemID = UUID.Zero;
1928 if (grp != null)
1929 {
1930 Vector3 inventoryStoredPosition = new Vector3
1931 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
1932 ? 250
1933 : grp.AbsolutePosition.X)
1934 ,
1935 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
1936 ? 250
1937 : grp.AbsolutePosition.X,
1938 grp.AbsolutePosition.Z);
1939
1940 Vector3 originalPosition = grp.AbsolutePosition;
1941
1942 grp.AbsolutePosition = inventoryStoredPosition;
1943
1944 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
1945
1946 grp.AbsolutePosition = originalPosition;
1947
1948 AssetBase asset = CreateAsset(
1949 grp.GetPartName(grp.LocalId),
1950 grp.GetPartDescription(grp.LocalId),
1951 (sbyte)AssetType.Object,
1952 Utils.StringToBytes(sceneObjectXml),
1953 remoteClient.AgentId);
1954 AssetService.Store(asset);
1955
1956 InventoryItemBase item = new InventoryItemBase();
1957 item.CreatorId = grp.RootPart.CreatorID.ToString();
1958 item.CreatorData = grp.RootPart.CreatorData;
1959 item.Owner = remoteClient.AgentId;
1960 item.ID = UUID.Random();
1961 item.AssetID = asset.FullID;
1962 item.Description = asset.Description;
1963 item.Name = asset.Name;
1964 item.AssetType = asset.Type;
1965 item.InvType = (int)InventoryType.Object;
1966
1967 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
1968 if (folder != null)
1969 item.Folder = folder.ID;
1970 else // oopsies
1971 item.Folder = UUID.Zero;
1972
1973 // Set up base perms properly
1974 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1975 permsBase &= grp.RootPart.BaseMask;
1976 permsBase |= (uint)PermissionMask.Move;
1977
1978 // Make sure we don't lock it
1979 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1980
1981 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1982 {
1983 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1984 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1985 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1986 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1987 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1988 }
1989 else
1990 {
1991 item.BasePermissions = permsBase;
1992 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1993 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1994 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1995 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1996 }
1997 item.CreationDate = Util.UnixTimeSinceEpoch();
1998
1999 // sets itemID so client can show item as 'attached' in inventory
2000 grp.SetFromItemID(item.ID);
2001
2002 if (AddInventoryItem(item))
2003 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2004 else
2005 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2006
2007 itemID = item.ID;
2008 return item.AssetID;
1880 } 2009 }
2010 return UUID.Zero;
1881 } 2011 }
1882 2012
1883 /// <summary> 2013 /// <summary>
@@ -2006,6 +2136,9 @@ namespace OpenSim.Region.Framework.Scenes
2006 2136
2007 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2137 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2008 { 2138 {
2139 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2140 return;
2141
2009 SceneObjectPart part = GetSceneObjectPart(objectID); 2142 SceneObjectPart part = GetSceneObjectPart(objectID);
2010 if (part == null) 2143 if (part == null)
2011 return; 2144 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 270e582..575079f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -374,7 +374,10 @@ namespace OpenSim.Region.Framework.Scenes
374 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query); 374 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query);
375 375
376 if (accounts == null) 376 if (accounts == null)
377 {
378 m_log.DebugFormat("[LLCIENT]: ProcessAvatarPickerRequest: returned null result");
377 return; 379 return;
380 }
378 381
379 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 382 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
380 // TODO: don't create new blocks if recycling an old packet 383 // TODO: don't create new blocks if recycling an old packet
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index e1fedf4..48beb9c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -49,6 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition); 49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition);
50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene); 50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene);
51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene); 51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool ViewObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene); 53 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene);
53 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene); 54 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene);
54 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene); 55 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene);
@@ -116,6 +117,7 @@ namespace OpenSim.Region.Framework.Scenes
116 public event DuplicateObjectHandler OnDuplicateObject; 117 public event DuplicateObjectHandler OnDuplicateObject;
117 public event EditObjectHandler OnEditObject; 118 public event EditObjectHandler OnEditObject;
118 public event EditObjectInventoryHandler OnEditObjectInventory; 119 public event EditObjectInventoryHandler OnEditObjectInventory;
120 public event ViewObjectInventoryHandler OnViewObjectInventory;
119 public event MoveObjectHandler OnMoveObject; 121 public event MoveObjectHandler OnMoveObject;
120 public event ObjectEntryHandler OnObjectEntry; 122 public event ObjectEntryHandler OnObjectEntry;
121 public event ReturnObjectsHandler OnReturnObjects; 123 public event ReturnObjectsHandler OnReturnObjects;
@@ -401,6 +403,21 @@ namespace OpenSim.Region.Framework.Scenes
401 return true; 403 return true;
402 } 404 }
403 405
406 public bool CanViewObjectInventory(UUID objectID, UUID editorID)
407 {
408 ViewObjectInventoryHandler handler = OnViewObjectInventory;
409 if (handler != null)
410 {
411 Delegate[] list = handler.GetInvocationList();
412 foreach (ViewObjectInventoryHandler h in list)
413 {
414 if (h(objectID, editorID, m_scene) == false)
415 return false;
416 }
417 }
418 return true;
419 }
420
404 #endregion 421 #endregion
405 422
406 #region MOVE OBJECT 423 #region MOVE OBJECT
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index eadec09..01ab199 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -93,6 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
93 // TODO: need to figure out how allow client agents but deny 93 // TODO: need to figure out how allow client agents but deny
94 // root agents when ACL denies access to root agent 94 // root agents when ACL denies access to root agent
95 public bool m_strictAccessControl = true; 95 public bool m_strictAccessControl = true;
96 public bool m_seeIntoBannedRegion = false;
96 public int MaxUndoCount = 5; 97 public int MaxUndoCount = 5;
97 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 98 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
98 public bool LoginLock = false; 99 public bool LoginLock = false;
@@ -108,12 +109,14 @@ namespace OpenSim.Region.Framework.Scenes
108 109
109 protected int m_splitRegionID; 110 protected int m_splitRegionID;
110 protected Timer m_restartWaitTimer = new Timer(); 111 protected Timer m_restartWaitTimer = new Timer();
112 protected Timer m_timerWatchdog = new Timer();
111 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 113 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
112 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 114 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
113 protected string m_simulatorVersion = "OpenSimulator Server"; 115 protected string m_simulatorVersion = "OpenSimulator Server";
114 protected ModuleLoader m_moduleLoader; 116 protected ModuleLoader m_moduleLoader;
115 protected AgentCircuitManager m_authenticateHandler; 117 protected AgentCircuitManager m_authenticateHandler;
116 protected SceneCommunicationService m_sceneGridService; 118 protected SceneCommunicationService m_sceneGridService;
119 protected ISnmpModule m_snmpService = null;
117 120
118 protected ISimulationDataService m_SimulationDataService; 121 protected ISimulationDataService m_SimulationDataService;
119 protected IEstateDataService m_EstateDataService; 122 protected IEstateDataService m_EstateDataService;
@@ -170,7 +173,7 @@ namespace OpenSim.Region.Framework.Scenes
170 private int m_update_events = 1; 173 private int m_update_events = 1;
171 private int m_update_backup = 200; 174 private int m_update_backup = 200;
172 private int m_update_terrain = 50; 175 private int m_update_terrain = 50;
173// private int m_update_land = 1; 176 private int m_update_land = 10;
174 private int m_update_coarse_locations = 50; 177 private int m_update_coarse_locations = 50;
175 178
176 private int frameMS; 179 private int frameMS;
@@ -184,14 +187,17 @@ namespace OpenSim.Region.Framework.Scenes
184 private int landMS; 187 private int landMS;
185 private int lastCompletedFrame; 188 private int lastCompletedFrame;
186 189
190 public bool CombineRegions = false;
187 private bool m_physics_enabled = true; 191 private bool m_physics_enabled = true;
188 private bool m_scripts_enabled = true; 192 private bool m_scripts_enabled = true;
189 private string m_defaultScriptEngine; 193 private string m_defaultScriptEngine;
190 private int m_LastLogin; 194 private int m_LastLogin;
191 private Thread HeartbeatThread; 195 private Thread HeartbeatThread = null;
192 private volatile bool shuttingdown; 196 private volatile bool shuttingdown;
193 197
194 private int m_lastUpdate; 198 private int m_lastUpdate;
199 private int m_lastIncoming;
200 private int m_lastOutgoing;
195 private bool m_firstHeartbeat = true; 201 private bool m_firstHeartbeat = true;
196 202
197 private object m_deleting_scene_object = new object(); 203 private object m_deleting_scene_object = new object();
@@ -244,6 +250,19 @@ namespace OpenSim.Region.Framework.Scenes
244 get { return m_sceneGridService; } 250 get { return m_sceneGridService; }
245 } 251 }
246 252
253 public ISnmpModule SnmpService
254 {
255 get
256 {
257 if (m_snmpService == null)
258 {
259 m_snmpService = RequestModuleInterface<ISnmpModule>();
260 }
261
262 return m_snmpService;
263 }
264 }
265
247 public ISimulationDataService SimulationDataService 266 public ISimulationDataService SimulationDataService
248 { 267 {
249 get 268 get
@@ -572,7 +591,10 @@ namespace OpenSim.Region.Framework.Scenes
572 m_regInfo = regInfo; 591 m_regInfo = regInfo;
573 m_regionHandle = m_regInfo.RegionHandle; 592 m_regionHandle = m_regInfo.RegionHandle;
574 m_regionName = m_regInfo.RegionName; 593 m_regionName = m_regInfo.RegionName;
594 m_datastore = m_regInfo.DataStore;
575 m_lastUpdate = Util.EnvironmentTickCount(); 595 m_lastUpdate = Util.EnvironmentTickCount();
596 m_lastIncoming = 0;
597 m_lastOutgoing = 0;
576 598
577 m_physicalPrim = physicalPrim; 599 m_physicalPrim = physicalPrim;
578 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor; 600 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
@@ -704,9 +726,10 @@ namespace OpenSim.Region.Framework.Scenes
704 //Animation states 726 //Animation states
705 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 727 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
706 // TODO: Change default to true once the feature is supported 728 // TODO: Change default to true once the feature is supported
707 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 729 m_usePreJump = startupConfig.GetBoolean("enableprejump", true);
708
709 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 730 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
731
732 m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF");
710 if (RegionInfo.NonphysPrimMax > 0) 733 if (RegionInfo.NonphysPrimMax > 0)
711 { 734 {
712 m_maxNonphys = RegionInfo.NonphysPrimMax; 735 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -738,6 +761,7 @@ namespace OpenSim.Region.Framework.Scenes
738 m_persistAfter *= 10000000; 761 m_persistAfter *= 10000000;
739 762
740 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 763 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
764 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
741 765
742 IConfig packetConfig = m_config.Configs["PacketPool"]; 766 IConfig packetConfig = m_config.Configs["PacketPool"];
743 if (packetConfig != null) 767 if (packetConfig != null)
@@ -747,6 +771,8 @@ namespace OpenSim.Region.Framework.Scenes
747 } 771 }
748 772
749 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 773 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
774 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
775 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
750 776
751 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 777 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
752 if (m_generateMaptiles) 778 if (m_generateMaptiles)
@@ -771,9 +797,9 @@ namespace OpenSim.Region.Framework.Scenes
771 } 797 }
772 } 798 }
773 } 799 }
774 catch 800 catch (Exception e)
775 { 801 {
776 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 802 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
777 } 803 }
778 804
779 #endregion Region Config 805 #endregion Region Config
@@ -1150,7 +1176,9 @@ namespace OpenSim.Region.Framework.Scenes
1150 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1176 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1151 if (HeartbeatThread != null) 1177 if (HeartbeatThread != null)
1152 { 1178 {
1179 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1153 HeartbeatThread.Abort(); 1180 HeartbeatThread.Abort();
1181 Watchdog.RemoveThread(HeartbeatThread.ManagedThreadId);
1154 HeartbeatThread = null; 1182 HeartbeatThread = null;
1155 } 1183 }
1156 m_lastUpdate = Util.EnvironmentTickCount(); 1184 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1193,9 +1221,6 @@ namespace OpenSim.Region.Framework.Scenes
1193 { 1221 {
1194 while (!shuttingdown) 1222 while (!shuttingdown)
1195 Update(); 1223 Update();
1196
1197 m_lastUpdate = Util.EnvironmentTickCount();
1198 m_firstHeartbeat = false;
1199 } 1224 }
1200 catch (ThreadAbortException) 1225 catch (ThreadAbortException)
1201 { 1226 {
@@ -1301,12 +1326,12 @@ namespace OpenSim.Region.Framework.Scenes
1301 terrainMS = Util.EnvironmentTickCountSubtract(terMS); 1326 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1302 } 1327 }
1303 1328
1304 //if (Frame % m_update_land == 0) 1329 // if (Frame % m_update_land == 0)
1305 //{ 1330 // {
1306 // int ldMS = Util.EnvironmentTickCount(); 1331 // int ldMS = Util.EnvironmentTickCount();
1307 // UpdateLand(); 1332 // UpdateLand();
1308 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1333 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1309 //} 1334 // }
1310 1335
1311 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); 1336 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
1312 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1337 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
@@ -1388,12 +1413,16 @@ namespace OpenSim.Region.Framework.Scenes
1388 maintc = Util.EnvironmentTickCountSubtract(maintc); 1413 maintc = Util.EnvironmentTickCountSubtract(maintc);
1389 maintc = (int)(m_timespan * 1000) - maintc; 1414 maintc = (int)(m_timespan * 1000) - maintc;
1390 1415
1416
1417 m_lastUpdate = Util.EnvironmentTickCount();
1418 m_firstHeartbeat = false;
1419
1391 if (maintc > 0) 1420 if (maintc > 0)
1392 Thread.Sleep(maintc); 1421 Thread.Sleep(maintc);
1393 1422
1394 // Tell the watchdog that this thread is still alive 1423 // Tell the watchdog that this thread is still alive
1395 Watchdog.UpdateThread(); 1424 Watchdog.UpdateThread();
1396 } 1425 }
1397 1426
1398 public void AddGroupTarget(SceneObjectGroup grp) 1427 public void AddGroupTarget(SceneObjectGroup grp)
1399 { 1428 {
@@ -1409,9 +1438,9 @@ namespace OpenSim.Region.Framework.Scenes
1409 1438
1410 private void CheckAtTargets() 1439 private void CheckAtTargets()
1411 { 1440 {
1412 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1441 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1413 lock (m_groupsWithTargets) 1442 lock (m_groupsWithTargets)
1414 objs = m_groupsWithTargets.Values; 1443 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1415 1444
1416 foreach (SceneObjectGroup entry in objs) 1445 foreach (SceneObjectGroup entry in objs)
1417 entry.checkAtTargets(); 1446 entry.checkAtTargets();
@@ -1731,14 +1760,24 @@ namespace OpenSim.Region.Framework.Scenes
1731 /// <returns></returns> 1760 /// <returns></returns>
1732 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1761 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1733 { 1762 {
1763
1764 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1765 Vector3 wpos = Vector3.Zero;
1766 // Check for water surface intersection from above
1767 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1768 {
1769 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1770 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1771 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1772 wpos.Z = wheight;
1773 }
1774
1734 Vector3 pos = Vector3.Zero; 1775 Vector3 pos = Vector3.Zero;
1735 if (RayEndIsIntersection == (byte)1) 1776 if (RayEndIsIntersection == (byte)1)
1736 { 1777 {
1737 pos = RayEnd; 1778 pos = RayEnd;
1738 return pos;
1739 } 1779 }
1740 1780 else if (RayTargetID != UUID.Zero)
1741 if (RayTargetID != UUID.Zero)
1742 { 1781 {
1743 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1782 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1744 1783
@@ -1760,7 +1799,7 @@ namespace OpenSim.Region.Framework.Scenes
1760 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1799 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1761 1800
1762 // Un-comment out the following line to Get Raytrace results printed to the console. 1801 // Un-comment out the following line to Get Raytrace results printed to the console.
1763 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1802 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1764 float ScaleOffset = 0.5f; 1803 float ScaleOffset = 0.5f;
1765 1804
1766 // If we hit something 1805 // If we hit something
@@ -1783,13 +1822,10 @@ namespace OpenSim.Region.Framework.Scenes
1783 //pos.Z -= 0.25F; 1822 //pos.Z -= 0.25F;
1784 1823
1785 } 1824 }
1786
1787 return pos;
1788 } 1825 }
1789 else 1826 else
1790 { 1827 {
1791 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1828 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1792
1793 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1829 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1794 1830
1795 // Un-comment the following line to print the raytrace results to the console. 1831 // Un-comment the following line to print the raytrace results to the console.
@@ -1798,13 +1834,12 @@ namespace OpenSim.Region.Framework.Scenes
1798 if (ei.HitTF) 1834 if (ei.HitTF)
1799 { 1835 {
1800 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1836 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1801 } else 1837 }
1838 else
1802 { 1839 {
1803 // fall back to our stupid functionality 1840 // fall back to our stupid functionality
1804 pos = RayEnd; 1841 pos = RayEnd;
1805 } 1842 }
1806
1807 return pos;
1808 } 1843 }
1809 } 1844 }
1810 else 1845 else
@@ -1815,8 +1850,12 @@ namespace OpenSim.Region.Framework.Scenes
1815 //increase height so its above the ground. 1850 //increase height so its above the ground.
1816 //should be getting the normal of the ground at the rez point and using that? 1851 //should be getting the normal of the ground at the rez point and using that?
1817 pos.Z += scale.Z / 2f; 1852 pos.Z += scale.Z / 2f;
1818 return pos; 1853// return pos;
1819 } 1854 }
1855
1856 // check against posible water intercept
1857 if (wpos.Z > pos.Z) pos = wpos;
1858 return pos;
1820 } 1859 }
1821 1860
1822 1861
@@ -1900,7 +1939,10 @@ namespace OpenSim.Region.Framework.Scenes
1900 public bool AddRestoredSceneObject( 1939 public bool AddRestoredSceneObject(
1901 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1940 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1902 { 1941 {
1903 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1942 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1943 if (result)
1944 sceneObject.IsDeleted = false;
1945 return result;
1904 } 1946 }
1905 1947
1906 /// <summary> 1948 /// <summary>
@@ -1990,6 +2032,15 @@ namespace OpenSim.Region.Framework.Scenes
1990 /// </summary> 2032 /// </summary>
1991 public void DeleteAllSceneObjects() 2033 public void DeleteAllSceneObjects()
1992 { 2034 {
2035 DeleteAllSceneObjects(false);
2036 }
2037
2038 /// <summary>
2039 /// Delete every object from the scene. This does not include attachments worn by avatars.
2040 /// </summary>
2041 public void DeleteAllSceneObjects(bool exceptNoCopy)
2042 {
2043 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1993 lock (Entities) 2044 lock (Entities)
1994 { 2045 {
1995 EntityBase[] entities = Entities.GetEntities(); 2046 EntityBase[] entities = Entities.GetEntities();
@@ -1998,11 +2049,24 @@ namespace OpenSim.Region.Framework.Scenes
1998 if (e is SceneObjectGroup) 2049 if (e is SceneObjectGroup)
1999 { 2050 {
2000 SceneObjectGroup sog = (SceneObjectGroup)e; 2051 SceneObjectGroup sog = (SceneObjectGroup)e;
2001 if (!sog.IsAttachment) 2052 if (sog != null && !sog.IsAttachment)
2002 DeleteSceneObject((SceneObjectGroup)e, false); 2053 {
2054 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2055 {
2056 DeleteSceneObject((SceneObjectGroup)e, false);
2057 }
2058 else
2059 {
2060 toReturn.Add((SceneObjectGroup)e);
2061 }
2062 }
2003 } 2063 }
2004 } 2064 }
2005 } 2065 }
2066 if (toReturn.Count > 0)
2067 {
2068 returnObjects(toReturn.ToArray(), UUID.Zero);
2069 }
2006 } 2070 }
2007 2071
2008 /// <summary> 2072 /// <summary>
@@ -2051,6 +2115,8 @@ namespace OpenSim.Region.Framework.Scenes
2051 } 2115 }
2052 2116
2053 group.DeleteGroupFromScene(silent); 2117 group.DeleteGroupFromScene(silent);
2118 if (!silent)
2119 SendKillObject(new List<uint>() { group.LocalId });
2054 2120
2055// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2121// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2056 } 2122 }
@@ -2405,10 +2471,17 @@ namespace OpenSim.Region.Framework.Scenes
2405 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2471 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2406 public bool AddSceneObject(SceneObjectGroup sceneObject) 2472 public bool AddSceneObject(SceneObjectGroup sceneObject)
2407 { 2473 {
2474 if (sceneObject.OwnerID == UUID.Zero)
2475 {
2476 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2477 return false;
2478 }
2479
2408 // If the user is banned, we won't let any of their objects 2480 // If the user is banned, we won't let any of their objects
2409 // enter. Period. 2481 // enter. Period.
2410 // 2482 //
2411 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2483 int flags = GetUserFlags(sceneObject.OwnerID);
2484 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2412 { 2485 {
2413 m_log.Info("[INTERREGION]: Denied prim crossing for " + 2486 m_log.Info("[INTERREGION]: Denied prim crossing for " +
2414 "banned avatar"); 2487 "banned avatar");
@@ -2452,15 +2525,28 @@ namespace OpenSim.Region.Framework.Scenes
2452 2525
2453 if (AttachmentsModule != null) 2526 if (AttachmentsModule != null)
2454 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2527 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2528
2529 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2455 } 2530 }
2456 else 2531 else
2457 { 2532 {
2533 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2458 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2534 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2459 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2535 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2460 } 2536 }
2537 if (sceneObject.OwnerID == UUID.Zero)
2538 {
2539 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2540 return false;
2541 }
2461 } 2542 }
2462 else 2543 else
2463 { 2544 {
2545 if (sceneObject.OwnerID == UUID.Zero)
2546 {
2547 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2548 return false;
2549 }
2464 AddRestoredSceneObject(sceneObject, true, false); 2550 AddRestoredSceneObject(sceneObject, true, false);
2465 2551
2466 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2552 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2490,6 +2576,24 @@ namespace OpenSim.Region.Framework.Scenes
2490 return 2; // StateSource.PrimCrossing 2576 return 2; // StateSource.PrimCrossing
2491 } 2577 }
2492 2578
2579 public int GetUserFlags(UUID user)
2580 {
2581 //Unfortunately the SP approach means that the value is cached until region is restarted
2582 /*
2583 ScenePresence sp;
2584 if (TryGetScenePresence(user, out sp))
2585 {
2586 return sp.UserFlags;
2587 }
2588 else
2589 {
2590 */
2591 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2592 if (uac == null)
2593 return 0;
2594 return uac.UserFlags;
2595 //}
2596 }
2493 #endregion 2597 #endregion
2494 2598
2495 #region Add/Remove Avatar Methods 2599 #region Add/Remove Avatar Methods
@@ -2511,6 +2615,7 @@ namespace OpenSim.Region.Framework.Scenes
2511 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2615 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2512 2616
2513 CheckHeartbeat(); 2617 CheckHeartbeat();
2618 ScenePresence presence;
2514 2619
2515 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here 2620 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here
2516 { 2621 {
@@ -2544,7 +2649,14 @@ namespace OpenSim.Region.Framework.Scenes
2544 2649
2545 EventManager.TriggerOnNewClient(client); 2650 EventManager.TriggerOnNewClient(client);
2546 if (vialogin) 2651 if (vialogin)
2652 {
2547 EventManager.TriggerOnClientLogin(client); 2653 EventManager.TriggerOnClientLogin(client);
2654
2655 // Send initial parcel data
2656 Vector3 pos = createdSp.AbsolutePosition;
2657 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2658 land.SendLandUpdateToClient(client);
2659 }
2548 } 2660 }
2549 } 2661 }
2550 2662
@@ -2633,19 +2745,12 @@ namespace OpenSim.Region.Framework.Scenes
2633 // and the scene presence and the client, if they exist 2745 // and the scene presence and the client, if they exist
2634 try 2746 try
2635 { 2747 {
2636 // We need to wait for the client to make UDP contact first. 2748 ScenePresence sp = GetScenePresence(agentID);
2637 // It's the UDP contact that creates the scene presence 2749 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2638 ScenePresence sp = WaitGetScenePresence(agentID); 2750
2639 if (sp != null) 2751 if (sp != null)
2640 {
2641 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2642
2643 sp.ControllingClient.Close(); 2752 sp.ControllingClient.Close();
2644 } 2753
2645 else
2646 {
2647 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2648 }
2649 // BANG! SLASH! 2754 // BANG! SLASH!
2650 m_authenticateHandler.RemoveCircuit(agentID); 2755 m_authenticateHandler.RemoveCircuit(agentID);
2651 2756
@@ -2745,6 +2850,7 @@ namespace OpenSim.Region.Framework.Scenes
2745 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2850 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2746 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2851 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2747 client.OnCopyInventoryItem += CopyInventoryItem; 2852 client.OnCopyInventoryItem += CopyInventoryItem;
2853 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2748 client.OnMoveInventoryItem += MoveInventoryItem; 2854 client.OnMoveInventoryItem += MoveInventoryItem;
2749 client.OnRemoveInventoryItem += RemoveInventoryItem; 2855 client.OnRemoveInventoryItem += RemoveInventoryItem;
2750 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2856 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2922,15 +3028,16 @@ namespace OpenSim.Region.Framework.Scenes
2922 /// </summary> 3028 /// </summary>
2923 /// <param name="agentId">The avatar's Unique ID</param> 3029 /// <param name="agentId">The avatar's Unique ID</param>
2924 /// <param name="client">The IClientAPI for the client</param> 3030 /// <param name="client">The IClientAPI for the client</param>
2925 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3031 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2926 { 3032 {
2927 if (m_teleportModule != null) 3033 if (m_teleportModule != null)
2928 m_teleportModule.TeleportHome(agentId, client); 3034 return m_teleportModule.TeleportHome(agentId, client);
2929 else 3035 else
2930 { 3036 {
2931 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3037 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2932 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3038 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2933 } 3039 }
3040 return false;
2934 } 3041 }
2935 3042
2936 /// <summary> 3043 /// <summary>
@@ -3022,6 +3129,16 @@ namespace OpenSim.Region.Framework.Scenes
3022 /// <param name="flags"></param> 3129 /// <param name="flags"></param>
3023 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3130 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3024 { 3131 {
3132 //Add half the avatar's height so that the user doesn't fall through prims
3133 ScenePresence presence;
3134 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3135 {
3136 if (presence.Appearance != null)
3137 {
3138 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3139 }
3140 }
3141
3025 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3142 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3026 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3143 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3027 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3144 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3096,8 +3213,9 @@ namespace OpenSim.Region.Framework.Scenes
3096 regions.Remove(RegionInfo.RegionHandle); 3213 regions.Remove(RegionInfo.RegionHandle);
3097 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3214 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3098 } 3215 }
3099 3216 m_log.Debug("[Scene] Beginning ClientClosed");
3100 m_eventManager.TriggerClientClosed(agentID, this); 3217 m_eventManager.TriggerClientClosed(agentID, this);
3218 m_log.Debug("[Scene] Finished ClientClosed");
3101 } 3219 }
3102 catch (NullReferenceException) 3220 catch (NullReferenceException)
3103 { 3221 {
@@ -3105,7 +3223,12 @@ namespace OpenSim.Region.Framework.Scenes
3105 // Avatar is already disposed :/ 3223 // Avatar is already disposed :/
3106 } 3224 }
3107 3225
3226 m_log.Debug("[Scene] Beginning OnRemovePresence");
3108 m_eventManager.TriggerOnRemovePresence(agentID); 3227 m_eventManager.TriggerOnRemovePresence(agentID);
3228 m_log.Debug("[Scene] Finished OnRemovePresence");
3229
3230 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
3231 AttachmentsModule.SaveChangedAttachments(avatar);
3109 3232
3110 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc) 3233 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
3111 AttachmentsModule.SaveChangedAttachments(avatar); 3234 AttachmentsModule.SaveChangedAttachments(avatar);
@@ -3114,7 +3237,7 @@ namespace OpenSim.Region.Framework.Scenes
3114 delegate(IClientAPI client) 3237 delegate(IClientAPI client)
3115 { 3238 {
3116 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3239 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3117 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3240 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3118 catch (NullReferenceException) { } 3241 catch (NullReferenceException) { }
3119 }); 3242 });
3120 3243
@@ -3125,8 +3248,11 @@ namespace OpenSim.Region.Framework.Scenes
3125 } 3248 }
3126 3249
3127 // Remove the avatar from the scene 3250 // Remove the avatar from the scene
3251 m_log.Debug("[Scene] Begin RemoveScenePresence");
3128 m_sceneGraph.RemoveScenePresence(agentID); 3252 m_sceneGraph.RemoveScenePresence(agentID);
3253 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3129 m_clientManager.Remove(agentID); 3254 m_clientManager.Remove(agentID);
3255 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3130 3256
3131 try 3257 try
3132 { 3258 {
@@ -3140,9 +3266,10 @@ namespace OpenSim.Region.Framework.Scenes
3140 { 3266 {
3141 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3267 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3142 } 3268 }
3143 3269 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3144 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3270 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3145// CleanDroppedAttachments(); 3271// CleanDroppedAttachments();
3272 m_log.Debug("[Scene] The avatar has left the building");
3146 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3273 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3147 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3274 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3148 } 3275 }
@@ -3173,19 +3300,24 @@ namespace OpenSim.Region.Framework.Scenes
3173 3300
3174 #region Entities 3301 #region Entities
3175 3302
3176 public void SendKillObject(uint localID) 3303 public void SendKillObject(List<uint> localIDs)
3177 { 3304 {
3178 SceneObjectPart part = GetSceneObjectPart(localID); 3305 List<uint> deleteIDs = new List<uint>();
3179 if (part != null) // It is a prim 3306
3307 foreach (uint localID in localIDs)
3180 { 3308 {
3181 if (!part.ParentGroup.IsDeleted) // Valid 3309 SceneObjectPart part = GetSceneObjectPart(localID);
3310 if (part != null) // It is a prim
3182 { 3311 {
3183 if (part.ParentGroup.RootPart != part) // Child part 3312 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3184 return; 3313 {
3314 if (part.ParentGroup.RootPart != part) // Child part
3315 continue;
3316 }
3185 } 3317 }
3318 deleteIDs.Add(localID);
3186 } 3319 }
3187 3320 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3188 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); });
3189 } 3321 }
3190 3322
3191 #endregion 3323 #endregion
@@ -3203,7 +3335,6 @@ namespace OpenSim.Region.Framework.Scenes
3203 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3335 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3204 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3336 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3205 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3337 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3206 m_sceneGridService.KiPrimitive += SendKillObject;
3207 m_sceneGridService.OnGetLandData += GetLandData; 3338 m_sceneGridService.OnGetLandData += GetLandData;
3208 } 3339 }
3209 3340
@@ -3212,7 +3343,6 @@ namespace OpenSim.Region.Framework.Scenes
3212 /// </summary> 3343 /// </summary>
3213 public void UnRegisterRegionWithComms() 3344 public void UnRegisterRegionWithComms()
3214 { 3345 {
3215 m_sceneGridService.KiPrimitive -= SendKillObject;
3216 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3346 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3217 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3347 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3218 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3348 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3292,13 +3422,16 @@ namespace OpenSim.Region.Framework.Scenes
3292 sp = null; 3422 sp = null;
3293 } 3423 }
3294 3424
3295 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3296 3425
3297 //On login test land permisions 3426 //On login test land permisions
3298 if (vialogin) 3427 if (vialogin)
3299 { 3428 {
3300 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3429 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3430 if (cache != null)
3431 cache.Remove(agent.firstname + " " + agent.lastname);
3432 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3301 { 3433 {
3434 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3302 return false; 3435 return false;
3303 } 3436 }
3304 } 3437 }
@@ -3321,8 +3454,13 @@ namespace OpenSim.Region.Framework.Scenes
3321 3454
3322 try 3455 try
3323 { 3456 {
3324 if (!AuthorizeUser(agent, out reason)) 3457 // Always check estate if this is a login. Always
3325 return false; 3458 // check if banned regions are to be blacked out.
3459 if (vialogin || (!m_seeIntoBannedRegion))
3460 {
3461 if (!AuthorizeUser(agent, out reason))
3462 return false;
3463 }
3326 } 3464 }
3327 catch (Exception e) 3465 catch (Exception e)
3328 { 3466 {
@@ -3424,6 +3562,8 @@ namespace OpenSim.Region.Framework.Scenes
3424 } 3562 }
3425 } 3563 }
3426 // Honor parcel landing type and position. 3564 // Honor parcel landing type and position.
3565 /*
3566 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3427 if (land != null) 3567 if (land != null)
3428 { 3568 {
3429 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3569 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3431,26 +3571,34 @@ namespace OpenSim.Region.Framework.Scenes
3431 agent.startpos = land.LandData.UserLocation; 3571 agent.startpos = land.LandData.UserLocation;
3432 } 3572 }
3433 } 3573 }
3574 */// This is now handled properly in ScenePresence.MakeRootAgent
3434 } 3575 }
3435 3576
3436 return true; 3577 return true;
3437 } 3578 }
3438 3579
3439 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3580 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3440 { 3581 {
3441 3582 reason = String.Empty;
3442 bool banned = land.IsBannedFromLand(agent.AgentID); 3583 if (Permissions.IsGod(agentID))
3443 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3584 return true;
3585
3586 ILandObject land = LandChannel.GetLandObject(posX, posY);
3587 if (land == null)
3588 return false;
3589
3590 bool banned = land.IsBannedFromLand(agentID);
3591 bool restricted = land.IsRestrictedFromLand(agentID);
3444 3592
3445 if (banned || restricted) 3593 if (banned || restricted)
3446 { 3594 {
3447 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3595 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3448 if (nearestParcel != null) 3596 if (nearestParcel != null)
3449 { 3597 {
3450 //Move agent to nearest allowed 3598 //Move agent to nearest allowed
3451 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3599 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3452 agent.startpos.X = newPosition.X; 3600 posX = newPosition.X;
3453 agent.startpos.Y = newPosition.Y; 3601 posY = newPosition.Y;
3454 } 3602 }
3455 else 3603 else
3456 { 3604 {
@@ -3512,7 +3660,7 @@ namespace OpenSim.Region.Framework.Scenes
3512 3660
3513 if (!m_strictAccessControl) return true; 3661 if (!m_strictAccessControl) return true;
3514 if (Permissions.IsGod(agent.AgentID)) return true; 3662 if (Permissions.IsGod(agent.AgentID)) return true;
3515 3663
3516 if (AuthorizationService != null) 3664 if (AuthorizationService != null)
3517 { 3665 {
3518 if (!AuthorizationService.IsAuthorizedForRegion( 3666 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3520,14 +3668,14 @@ namespace OpenSim.Region.Framework.Scenes
3520 { 3668 {
3521 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3669 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3522 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3670 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3523 3671
3524 return false; 3672 return false;
3525 } 3673 }
3526 } 3674 }
3527 3675
3528 if (m_regInfo.EstateSettings != null) 3676 if (m_regInfo.EstateSettings != null)
3529 { 3677 {
3530 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3678 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3531 { 3679 {
3532 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3680 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3533 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3681 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3717,6 +3865,13 @@ namespace OpenSim.Region.Framework.Scenes
3717 3865
3718 // We have to wait until the viewer contacts this region after receiving EAC. 3866 // We have to wait until the viewer contacts this region after receiving EAC.
3719 // That calls AddNewClient, which finally creates the ScenePresence 3867 // That calls AddNewClient, which finally creates the ScenePresence
3868 int flags = GetUserFlags(cAgentData.AgentID);
3869 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3870 {
3871 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3872 return false;
3873 }
3874
3720 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3875 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3721 if (nearestParcel == null) 3876 if (nearestParcel == null)
3722 { 3877 {
@@ -3732,7 +3887,6 @@ namespace OpenSim.Region.Framework.Scenes
3732 return false; 3887 return false;
3733 } 3888 }
3734 3889
3735
3736 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3890 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3737 3891
3738 if (childAgentUpdate != null) 3892 if (childAgentUpdate != null)
@@ -3799,12 +3953,22 @@ namespace OpenSim.Region.Framework.Scenes
3799 return false; 3953 return false;
3800 } 3954 }
3801 3955
3956 public bool IncomingCloseAgent(UUID agentID)
3957 {
3958 return IncomingCloseAgent(agentID, false);
3959 }
3960
3961 public bool IncomingCloseChildAgent(UUID agentID)
3962 {
3963 return IncomingCloseAgent(agentID, true);
3964 }
3965
3802 /// <summary> 3966 /// <summary>
3803 /// Tell a single agent to disconnect from the region. 3967 /// Tell a single agent to disconnect from the region.
3804 /// </summary> 3968 /// </summary>
3805 /// <param name="regionHandle"></param>
3806 /// <param name="agentID"></param> 3969 /// <param name="agentID"></param>
3807 public bool IncomingCloseAgent(UUID agentID) 3970 /// <param name="childOnly"></param>
3971 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3808 { 3972 {
3809 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3973 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3810 3974
@@ -3816,7 +3980,7 @@ namespace OpenSim.Region.Framework.Scenes
3816 { 3980 {
3817 m_sceneGraph.removeUserCount(false); 3981 m_sceneGraph.removeUserCount(false);
3818 } 3982 }
3819 else 3983 else if (!childOnly)
3820 { 3984 {
3821 m_sceneGraph.removeUserCount(true); 3985 m_sceneGraph.removeUserCount(true);
3822 } 3986 }
@@ -3832,9 +3996,12 @@ namespace OpenSim.Region.Framework.Scenes
3832 } 3996 }
3833 else 3997 else
3834 presence.ControllingClient.SendShutdownConnectionNotice(); 3998 presence.ControllingClient.SendShutdownConnectionNotice();
3999 presence.ControllingClient.Close(false);
4000 }
4001 else if (!childOnly)
4002 {
4003 presence.ControllingClient.Close(true);
3835 } 4004 }
3836
3837 presence.ControllingClient.Close();
3838 return true; 4005 return true;
3839 } 4006 }
3840 4007
@@ -4449,34 +4616,66 @@ namespace OpenSim.Region.Framework.Scenes
4449 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4616 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4450 } 4617 }
4451 4618
4452 public int GetHealth() 4619 public int GetHealth(out int flags, out string message)
4453 { 4620 {
4454 // Returns: 4621 // Returns:
4455 // 1 = sim is up and accepting http requests. The heartbeat has 4622 // 1 = sim is up and accepting http requests. The heartbeat has
4456 // stopped and the sim is probably locked up, but a remote 4623 // stopped and the sim is probably locked up, but a remote
4457 // admin restart may succeed 4624 // admin restart may succeed
4458 // 4625 //
4459 // 2 = Sim is up and the heartbeat is running. The sim is likely 4626 // 2 = Sim is up and the heartbeat is running. The sim is likely
4460 // usable for people within and logins _may_ work 4627 // usable for people within
4628 //
4629 // 3 = Sim is up and one packet thread is running. Sim is
4630 // unstable and will not accept new logins
4461 // 4631 //
4462 // 3 = We have seen a new user enter within the past 4 minutes 4632 // 4 = Sim is up and both packet threads are running. Sim is
4633 // likely usable
4634 //
4635 // 5 = We have seen a new user enter within the past 4 minutes
4463 // which can be seen as positive confirmation of sim health 4636 // which can be seen as positive confirmation of sim health
4464 // 4637 //
4638
4639 flags = 0;
4640 message = String.Empty;
4641
4642 CheckHeartbeat();
4643
4644 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4645 {
4646 // We're still starting
4647 // 0 means "in startup", it can't happen another way, since
4648 // to get here, we must be able to accept http connections
4649 return 0;
4650 }
4651
4465 int health=1; // Start at 1, means we're up 4652 int health=1; // Start at 1, means we're up
4466 4653
4467 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4654 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4655 {
4468 health+=1; 4656 health+=1;
4469 else 4657 flags |= 1;
4658 }
4659
4660 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4661 {
4662 health+=1;
4663 flags |= 2;
4664 }
4665
4666 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4667 {
4668 health+=1;
4669 flags |= 4;
4670 }
4671
4672 if (flags != 7)
4470 return health; 4673 return health;
4471 4674
4472 // A login in the last 4 mins? We can't be doing too badly 4675 // A login in the last 4 mins? We can't be doing too badly
4473 // 4676 //
4474 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4677 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4475 health++; 4678 health++;
4476 else
4477 return health;
4478
4479 CheckHeartbeat();
4480 4679
4481 return health; 4680 return health;
4482 } 4681 }
@@ -4669,7 +4868,7 @@ namespace OpenSim.Region.Framework.Scenes
4669 if (m_firstHeartbeat) 4868 if (m_firstHeartbeat)
4670 return; 4869 return;
4671 4870
4672 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4871 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4673 StartTimer(); 4872 StartTimer();
4674 } 4873 }
4675 4874
@@ -5118,6 +5317,19 @@ namespace OpenSim.Region.Framework.Scenes
5118// } 5317// }
5119// } 5318// }
5120 5319
5320 public void ThreadAlive(int threadCode)
5321 {
5322 switch(threadCode)
5323 {
5324 case 1: // Incoming
5325 m_lastIncoming = Util.EnvironmentTickCount();
5326 break;
5327 case 2: // Incoming
5328 m_lastOutgoing = Util.EnvironmentTickCount();
5329 break;
5330 }
5331 }
5332
5121 // This method is called across the simulation connector to 5333 // This method is called across the simulation connector to
5122 // determine if a given agent is allowed in this region 5334 // determine if a given agent is allowed in this region
5123 // AS A ROOT AGENT. Returning false here will prevent them 5335 // AS A ROOT AGENT. Returning false here will prevent them
@@ -5126,6 +5338,14 @@ namespace OpenSim.Region.Framework.Scenes
5126 // child agent creation, thereby emulating the SL behavior. 5338 // child agent creation, thereby emulating the SL behavior.
5127 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5339 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5128 { 5340 {
5341 reason = "You are banned from the region";
5342
5343 if (Permissions.IsGod(agentID))
5344 {
5345 reason = String.Empty;
5346 return true;
5347 }
5348
5129 int num = m_sceneGraph.GetNumberOfScenePresences(); 5349 int num = m_sceneGraph.GetNumberOfScenePresences();
5130 5350
5131 if (num >= RegionInfo.RegionSettings.AgentLimit) 5351 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5137,11 +5357,60 @@ namespace OpenSim.Region.Framework.Scenes
5137 } 5357 }
5138 } 5358 }
5139 5359
5360 try
5361 {
5362 if (!AuthorizeUser(GetScenePresence(agentID).ControllingClient.RequestClientInfo(), out reason))
5363 {
5364 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5365 return false;
5366 }
5367 }
5368 catch
5369 {
5370 return false;
5371 }
5372
5373 if (position == Vector3.Zero) // Teleport
5374 {
5375 float posX = 128.0f;
5376 float posY = 128.0f;
5377
5378 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5379 {
5380 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5381 return false;
5382 }
5383 }
5384 else // Walking
5385 {
5386 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5387 if (land == null)
5388 return false;
5389
5390 bool banned = land.IsBannedFromLand(agentID);
5391 bool restricted = land.IsRestrictedFromLand(agentID);
5392
5393 if (banned || restricted)
5394 return false;
5395 }
5396
5140 reason = String.Empty; 5397 reason = String.Empty;
5141 return true; 5398 return true;
5142 } 5399 }
5143 5400
5144 /// <summary> 5401 public void StartTimerWatchdog()
5402 {
5403 m_timerWatchdog.Interval = 1000;
5404 m_timerWatchdog.Elapsed += TimerWatchdog;
5405 m_timerWatchdog.AutoReset = true;
5406 m_timerWatchdog.Start();
5407 }
5408
5409 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5410 {
5411 CheckHeartbeat();
5412 }
5413
5145 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5414 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5146 /// autopilot that moves an avatar to a sit target!. 5415 /// autopilot that moves an avatar to a sit target!.
5147 /// </summary> 5416 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index ec94f10..bf861b8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 837e655..19cb0c1 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;
@@ -259,46 +255,42 @@ namespace OpenSim.Region.Framework.Scenes
259 255
260 } 256 }
261 257
262 //public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle); 258 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
263 //private void SendCloseChildAgentCompleted(IAsyncResult iar)
264 //{
265 // SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
266 // icon.EndInvoke(iar);
267 //}
268 259
269 /// <summary> 260 /// <summary>
270 /// Closes a child agent on a given region 261 /// This Closes child agents on neighboring regions
262 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
271 /// </summary> 263 /// </summary>
272 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 264 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
273 { 265 {
274 266
275 m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); 267 //m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
276 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 268 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
277 269
278 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 270 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
279 uint x = 0, y = 0; 271 uint x = 0, y = 0;
280 Utils.LongToUInts(regionHandle, out x, out y); 272 Utils.LongToUInts(regionHandle, out x, out y);
281 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 273 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
282 m_scene.SimulationService.CloseAgent(destination, agentID); 274 m_scene.SimulationService.CloseChildAgent(destination, agentID);
275 }
276
277 private void SendCloseChildAgentCompleted(IAsyncResult iar)
278 {
279 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
280 icon.EndInvoke(iar);
283 } 281 }
284 282
285 /// <summary>
286 /// Closes a child agents in a collection of regions. Does so asynchronously
287 /// so that the caller doesn't wait.
288 /// </summary>
289 /// <param name="agentID"></param>
290 /// <param name="regionslst"></param>
291 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 283 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
292 { 284 {
293 Util.FireAndForget(delegate 285 foreach (ulong handle in regionslst)
294 { 286 {
295 foreach (ulong handle in regionslst) 287 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
296 { 288 d.BeginInvoke(agentID, handle,
297 SendCloseChildAgent(agentID, handle); 289 SendCloseChildAgentCompleted,
298 } 290 d);
299 }); 291 }
300 } 292 }
301 293
302 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 294 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
303 { 295 {
304 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 296 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 36c5c52..d1ee990 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
@@ -132,13 +141,18 @@ namespace OpenSim.Region.Framework.Scenes
132 141
133 protected internal void Close() 142 protected internal void Close()
134 { 143 {
135 lock (m_presenceLock) 144 m_scenePresencesLock.EnterWriteLock();
145 try
136 { 146 {
137 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 147 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
138 List<ScenePresence> newlist = new List<ScenePresence>(); 148 List<ScenePresence> newlist = new List<ScenePresence>();
139 m_scenePresenceMap = newmap; 149 m_scenePresenceMap = newmap;
140 m_scenePresenceArray = newlist; 150 m_scenePresenceArray = newlist;
141 } 151 }
152 finally
153 {
154 m_scenePresencesLock.ExitWriteLock();
155 }
142 156
143 lock (SceneObjectGroupsByFullID) 157 lock (SceneObjectGroupsByFullID)
144 SceneObjectGroupsByFullID.Clear(); 158 SceneObjectGroupsByFullID.Clear();
@@ -270,6 +284,33 @@ namespace OpenSim.Region.Framework.Scenes
270 protected internal bool AddRestoredSceneObject( 284 protected internal bool AddRestoredSceneObject(
271 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 285 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
272 { 286 {
287 if (!m_parentScene.CombineRegions)
288 {
289 // KF: Check for out-of-region, move inside and make static.
290 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
291 sceneObject.RootPart.GroupPosition.Y,
292 sceneObject.RootPart.GroupPosition.Z);
293 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 ||
294 npos.X > Constants.RegionSize ||
295 npos.Y > Constants.RegionSize))
296 {
297 if (npos.X < 0.0) npos.X = 1.0f;
298 if (npos.Y < 0.0) npos.Y = 1.0f;
299 if (npos.Z < 0.0) npos.Z = 0.0f;
300 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
301 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
302
303 foreach (SceneObjectPart part in sceneObject.Parts)
304 {
305 part.GroupPosition = npos;
306 }
307 sceneObject.RootPart.Velocity = Vector3.Zero;
308 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
309 sceneObject.RootPart.Acceleration = Vector3.Zero;
310 sceneObject.RootPart.Velocity = Vector3.Zero;
311 }
312 }
313
273 if (attachToBackup && (!alreadyPersisted)) 314 if (attachToBackup && (!alreadyPersisted))
274 { 315 {
275 sceneObject.ForceInventoryPersistence(); 316 sceneObject.ForceInventoryPersistence();
@@ -487,6 +528,30 @@ namespace OpenSim.Region.Framework.Scenes
487 m_updateList[obj.UUID] = obj; 528 m_updateList[obj.UUID] = obj;
488 } 529 }
489 530
531 public void FireAttachToBackup(SceneObjectGroup obj)
532 {
533 if (OnAttachToBackup != null)
534 {
535 OnAttachToBackup(obj);
536 }
537 }
538
539 public void FireDetachFromBackup(SceneObjectGroup obj)
540 {
541 if (OnDetachFromBackup != null)
542 {
543 OnDetachFromBackup(obj);
544 }
545 }
546
547 public void FireChangeBackup(SceneObjectGroup obj)
548 {
549 if (OnChangeBackup != null)
550 {
551 OnChangeBackup(obj);
552 }
553 }
554
490 /// <summary> 555 /// <summary>
491 /// Process all pending updates 556 /// Process all pending updates
492 /// </summary> 557 /// </summary>
@@ -618,7 +683,8 @@ namespace OpenSim.Region.Framework.Scenes
618 683
619 Entities[presence.UUID] = presence; 684 Entities[presence.UUID] = presence;
620 685
621 lock (m_presenceLock) 686 m_scenePresencesLock.EnterWriteLock();
687 try
622 { 688 {
623 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 689 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
624 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 690 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -642,6 +708,10 @@ namespace OpenSim.Region.Framework.Scenes
642 m_scenePresenceMap = newmap; 708 m_scenePresenceMap = newmap;
643 m_scenePresenceArray = newlist; 709 m_scenePresenceArray = newlist;
644 } 710 }
711 finally
712 {
713 m_scenePresencesLock.ExitWriteLock();
714 }
645 } 715 }
646 716
647 /// <summary> 717 /// <summary>
@@ -656,7 +726,8 @@ namespace OpenSim.Region.Framework.Scenes
656 agentID); 726 agentID);
657 } 727 }
658 728
659 lock (m_presenceLock) 729 m_scenePresencesLock.EnterWriteLock();
730 try
660 { 731 {
661 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 732 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
662 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 733 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -678,6 +749,10 @@ namespace OpenSim.Region.Framework.Scenes
678 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 749 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
679 } 750 }
680 } 751 }
752 finally
753 {
754 m_scenePresencesLock.ExitWriteLock();
755 }
681 } 756 }
682 757
683 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 758 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1377,8 +1452,13 @@ namespace OpenSim.Region.Framework.Scenes
1377 { 1452 {
1378 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1453 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1379 { 1454 {
1380 if (m_parentScene.AttachmentsModule != null) 1455 // Set the new attachment point data in the object
1381 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1456 byte attachmentPoint = group.GetAttachmentPoint();
1457 group.UpdateGroupPosition(pos);
1458 group.IsAttachment = false;
1459 group.AbsolutePosition = group.RootPart.AttachedPos;
1460 group.AttachmentPoint = attachmentPoint;
1461 group.HasGroupChanged = true;
1382 } 1462 }
1383 else 1463 else
1384 { 1464 {
@@ -1642,10 +1722,13 @@ namespace OpenSim.Region.Framework.Scenes
1642 /// <param name="childPrims"></param> 1722 /// <param name="childPrims"></param>
1643 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1723 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1644 { 1724 {
1725 SceneObjectGroup parentGroup = root.ParentGroup;
1726 if (parentGroup == null) return;
1645 Monitor.Enter(m_updateLock); 1727 Monitor.Enter(m_updateLock);
1728
1646 try 1729 try
1647 { 1730 {
1648 SceneObjectGroup parentGroup = root.ParentGroup; 1731 parentGroup.areUpdatesSuspended = true;
1649 1732
1650 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1733 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1651 1734
@@ -1657,9 +1740,13 @@ namespace OpenSim.Region.Framework.Scenes
1657 // Make sure no child prim is set for sale 1740 // Make sure no child prim is set for sale
1658 // So that, on delink, no prims are unwittingly 1741 // So that, on delink, no prims are unwittingly
1659 // left for sale and sold off 1742 // left for sale and sold off
1660 child.RootPart.ObjectSaleType = 0; 1743
1661 child.RootPart.SalePrice = 10; 1744 if (child != null)
1662 childGroups.Add(child); 1745 {
1746 child.RootPart.ObjectSaleType = 0;
1747 child.RootPart.SalePrice = 10;
1748 childGroups.Add(child);
1749 }
1663 } 1750 }
1664 1751
1665 foreach (SceneObjectGroup child in childGroups) 1752 foreach (SceneObjectGroup child in childGroups)
@@ -1675,12 +1762,13 @@ namespace OpenSim.Region.Framework.Scenes
1675 // occur on link to invoke this elsewhere (such as object selection) 1762 // occur on link to invoke this elsewhere (such as object selection)
1676 parentGroup.RootPart.CreateSelected = true; 1763 parentGroup.RootPart.CreateSelected = true;
1677 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1764 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1678 parentGroup.HasGroupChanged = true;
1679 parentGroup.ScheduleGroupForFullUpdate();
1680
1681 } 1765 }
1682 finally 1766 finally
1683 { 1767 {
1768 parentGroup.areUpdatesSuspended = false;
1769 parentGroup.HasGroupChanged = true;
1770 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1771 parentGroup.ScheduleGroupForFullUpdate();
1684 Monitor.Exit(m_updateLock); 1772 Monitor.Exit(m_updateLock);
1685 } 1773 }
1686 } 1774 }
@@ -1712,21 +1800,24 @@ namespace OpenSim.Region.Framework.Scenes
1712 1800
1713 SceneObjectGroup group = part.ParentGroup; 1801 SceneObjectGroup group = part.ParentGroup;
1714 if (!affectedGroups.Contains(group)) 1802 if (!affectedGroups.Contains(group))
1803 {
1804 group.areUpdatesSuspended = true;
1715 affectedGroups.Add(group); 1805 affectedGroups.Add(group);
1806 }
1716 } 1807 }
1717 } 1808 }
1718 } 1809 }
1719 1810
1720 foreach (SceneObjectPart child in childParts) 1811 if (childParts.Count > 0)
1721 { 1812 {
1722 // Unlink all child parts from their groups 1813 foreach (SceneObjectPart child in childParts)
1723 // 1814 {
1724 child.ParentGroup.DelinkFromGroup(child, true); 1815 // Unlink all child parts from their groups
1725 1816 //
1726 // These are not in affected groups and will not be 1817 child.ParentGroup.DelinkFromGroup(child, true);
1727 // handled further. Do the honors here. 1818 child.ParentGroup.HasGroupChanged = true;
1728 child.ParentGroup.HasGroupChanged = true; 1819 child.ParentGroup.ScheduleGroupForFullUpdate();
1729 child.ParentGroup.ScheduleGroupForFullUpdate(); 1820 }
1730 } 1821 }
1731 1822
1732 foreach (SceneObjectPart root in rootParts) 1823 foreach (SceneObjectPart root in rootParts)
@@ -1736,56 +1827,68 @@ namespace OpenSim.Region.Framework.Scenes
1736 // However, editing linked parts and unlinking may be different 1827 // However, editing linked parts and unlinking may be different
1737 // 1828 //
1738 SceneObjectGroup group = root.ParentGroup; 1829 SceneObjectGroup group = root.ParentGroup;
1830 group.areUpdatesSuspended = true;
1739 1831
1740 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1832 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1741 int numChildren = newSet.Count; 1833 int numChildren = newSet.Count;
1742 1834
1835 if (numChildren == 1)
1836 break;
1837
1743 // If there are prims left in a link set, but the root is 1838 // If there are prims left in a link set, but the root is
1744 // slated for unlink, we need to do this 1839 // slated for unlink, we need to do this
1840 // Unlink the remaining set
1745 // 1841 //
1746 if (numChildren != 1) 1842 bool sendEventsToRemainder = true;
1747 { 1843 if (numChildren > 1)
1748 // Unlink the remaining set 1844 sendEventsToRemainder = false;
1749 //
1750 bool sendEventsToRemainder = true;
1751 if (numChildren > 1)
1752 sendEventsToRemainder = false;
1753 1845
1754 foreach (SceneObjectPart p in newSet) 1846 foreach (SceneObjectPart p in newSet)
1847 {
1848 if (p != group.RootPart)
1755 { 1849 {
1756 if (p != group.RootPart) 1850 group.DelinkFromGroup(p, sendEventsToRemainder);
1757 group.DelinkFromGroup(p, sendEventsToRemainder); 1851 if (numChildren > 2)
1852 {
1853 p.ParentGroup.areUpdatesSuspended = true;
1854 }
1855 else
1856 {
1857 p.ParentGroup.HasGroupChanged = true;
1858 p.ParentGroup.ScheduleGroupForFullUpdate();
1859 }
1758 } 1860 }
1861 }
1759 1862
1760 // If there is more than one prim remaining, we 1863 // If there is more than one prim remaining, we
1761 // need to re-link 1864 // need to re-link
1865 //
1866 if (numChildren > 2)
1867 {
1868 // Remove old root
1869 //
1870 if (newSet.Contains(root))
1871 newSet.Remove(root);
1872
1873 // Preserve link ordering
1762 // 1874 //
1763 if (numChildren > 2) 1875 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1764 { 1876 {
1765 // Remove old root 1877 return a.LinkNum.CompareTo(b.LinkNum);
1766 // 1878 });
1767 if (newSet.Contains(root))
1768 newSet.Remove(root);
1769
1770 // Preserve link ordering
1771 //
1772 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1773 {
1774 return a.LinkNum.CompareTo(b.LinkNum);
1775 });
1776 1879
1777 // Determine new root 1880 // Determine new root
1778 // 1881 //
1779 SceneObjectPart newRoot = newSet[0]; 1882 SceneObjectPart newRoot = newSet[0];
1780 newSet.RemoveAt(0); 1883 newSet.RemoveAt(0);
1781 1884
1782 foreach (SceneObjectPart newChild in newSet) 1885 foreach (SceneObjectPart newChild in newSet)
1783 newChild.UpdateFlag = 0; 1886 newChild.UpdateFlag = 0;
1784 1887
1785 LinkObjects(newRoot, newSet); 1888 newRoot.ParentGroup.areUpdatesSuspended = true;
1786 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1889 LinkObjects(newRoot, newSet);
1787 affectedGroups.Add(newRoot.ParentGroup); 1890 if (!affectedGroups.Contains(newRoot.ParentGroup))
1788 } 1891 affectedGroups.Add(newRoot.ParentGroup);
1789 } 1892 }
1790 } 1893 }
1791 1894
@@ -1793,8 +1896,14 @@ namespace OpenSim.Region.Framework.Scenes
1793 // 1896 //
1794 foreach (SceneObjectGroup g in affectedGroups) 1897 foreach (SceneObjectGroup g in affectedGroups)
1795 { 1898 {
1899 // Child prims that have been unlinked and deleted will
1900 // return unless the root is deleted. This will remove them
1901 // from the database. They will be rewritten immediately,
1902 // minus the rows for the unlinked child prims.
1903 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1796 g.TriggerScriptChangedEvent(Changed.LINK); 1904 g.TriggerScriptChangedEvent(Changed.LINK);
1797 g.HasGroupChanged = true; // Persist 1905 g.HasGroupChanged = true; // Persist
1906 g.areUpdatesSuspended = false;
1798 g.ScheduleGroupForFullUpdate(); 1907 g.ScheduleGroupForFullUpdate();
1799 } 1908 }
1800 } 1909 }
@@ -1912,9 +2021,6 @@ namespace OpenSim.Region.Framework.Scenes
1912 child.ApplyNextOwnerPermissions(); 2021 child.ApplyNextOwnerPermissions();
1913 } 2022 }
1914 } 2023 }
1915
1916 copy.RootPart.ObjectSaleType = 0;
1917 copy.RootPart.SalePrice = 10;
1918 } 2024 }
1919 2025
1920 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2026 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 905ecc9..6bd9183 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();
@@ -385,6 +381,9 @@ namespace OpenSim.Region.Framework.Scenes
385 381
386 public void ResumeScripts() 382 public void ResumeScripts()
387 { 383 {
384 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
385 return;
386
388 SceneObjectPart[] parts = m_parts.GetArray(); 387 SceneObjectPart[] parts = m_parts.GetArray();
389 for (int i = 0; i < parts.Length; i++) 388 for (int i = 0; i < parts.Length; i++)
390 parts[i].Inventory.ResumeScripts(); 389 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 234eb7d..17f02c2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,11 +24,12 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -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
@@ -131,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 183 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
132 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 184 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 185 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 186 public bool HasGroupChangedDueToDelink { get; set; }
135 187
136 private bool isTimeToPersist() 188 private bool isTimeToPersist()
137 { 189 {
@@ -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 }
@@ -247,10 +310,10 @@ namespace OpenSim.Region.Framework.Scenes
247 310
248 private bool m_scriptListens_atTarget; 311 private bool m_scriptListens_atTarget;
249 private bool m_scriptListens_notAtTarget; 312 private bool m_scriptListens_notAtTarget;
250
251 private bool m_scriptListens_atRotTarget; 313 private bool m_scriptListens_atRotTarget;
252 private bool m_scriptListens_notAtRotTarget; 314 private bool m_scriptListens_notAtRotTarget;
253 315
316 public bool m_dupeInProgress = false;
254 internal Dictionary<UUID, string> m_savedScriptState; 317 internal Dictionary<UUID, string> m_savedScriptState;
255 318
256 #region Properties 319 #region Properties
@@ -286,7 +349,9 @@ namespace OpenSim.Region.Framework.Scenes
286 public virtual Quaternion Rotation 349 public virtual Quaternion Rotation
287 { 350 {
288 get { return m_rotation; } 351 get { return m_rotation; }
289 set { m_rotation = value; } 352 set {
353 m_rotation = value;
354 }
290 } 355 }
291 356
292 public Quaternion GroupRotation 357 public Quaternion GroupRotation
@@ -397,7 +462,11 @@ namespace OpenSim.Region.Framework.Scenes
397 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 462 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
398 } 463 }
399 } 464 }
400 465
466 foreach (SceneObjectPart part in m_parts.GetArray())
467 {
468 part.IgnoreUndoUpdate = true;
469 }
401 if (RootPart.GetStatusSandbox()) 470 if (RootPart.GetStatusSandbox())
402 { 471 {
403 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 472 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -411,10 +480,29 @@ namespace OpenSim.Region.Framework.Scenes
411 return; 480 return;
412 } 481 }
413 } 482 }
414
415 SceneObjectPart[] parts = m_parts.GetArray(); 483 SceneObjectPart[] parts = m_parts.GetArray();
416 for (int i = 0; i < parts.Length; i++) 484 foreach (SceneObjectPart part in parts)
417 parts[i].GroupPosition = val; 485 {
486 part.GroupPosition = val;
487 if (!m_dupeInProgress)
488 {
489 part.TriggerScriptChangedEvent(Changed.POSITION);
490 }
491 }
492 if (!m_dupeInProgress)
493 {
494 foreach (ScenePresence av in m_linkedAvatars)
495 {
496 SceneObjectPart p;
497 if (m_parts.TryGetValue(av.LinkedPrim, out p))
498 {
499 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
500 av.AbsolutePosition += offset;
501 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
502 av.SendAvatarDataToAllAgents();
503 }
504 }
505 }
418 506
419 //if (m_rootPart.PhysActor != null) 507 //if (m_rootPart.PhysActor != null)
420 //{ 508 //{
@@ -573,6 +661,7 @@ namespace OpenSim.Region.Framework.Scenes
573 /// </summary> 661 /// </summary>
574 public SceneObjectGroup() 662 public SceneObjectGroup()
575 { 663 {
664
576 } 665 }
577 666
578 /// <summary> 667 /// <summary>
@@ -589,7 +678,7 @@ namespace OpenSim.Region.Framework.Scenes
589 /// Constructor. This object is added to the scene later via AttachToScene() 678 /// Constructor. This object is added to the scene later via AttachToScene()
590 /// </summary> 679 /// </summary>
591 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 680 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
592 { 681 {
593 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 682 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
594 } 683 }
595 684
@@ -637,6 +726,9 @@ namespace OpenSim.Region.Framework.Scenes
637 /// </summary> 726 /// </summary>
638 public virtual void AttachToBackup() 727 public virtual void AttachToBackup()
639 { 728 {
729 if (IsAttachment) return;
730 m_scene.SceneGraph.FireAttachToBackup(this);
731
640 if (InSceneBackup) 732 if (InSceneBackup)
641 { 733 {
642 //m_log.DebugFormat( 734 //m_log.DebugFormat(
@@ -679,6 +771,9 @@ namespace OpenSim.Region.Framework.Scenes
679 771
680 ApplyPhysics(m_scene.m_physicalPrim); 772 ApplyPhysics(m_scene.m_physicalPrim);
681 773
774 if (RootPart.PhysActor != null)
775 RootPart.Buoyancy = RootPart.Buoyancy;
776
682 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 777 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
683 // for the same object with very different properties. The caller must schedule the update. 778 // for the same object with very different properties. The caller must schedule the update.
684 //ScheduleGroupForFullUpdate(); 779 //ScheduleGroupForFullUpdate();
@@ -724,9 +819,9 @@ namespace OpenSim.Region.Framework.Scenes
724 result.normal = inter.normal; 819 result.normal = inter.normal;
725 result.distance = inter.distance; 820 result.distance = inter.distance;
726 } 821 }
822
727 } 823 }
728 } 824 }
729
730 return result; 825 return result;
731 } 826 }
732 827
@@ -746,17 +841,19 @@ namespace OpenSim.Region.Framework.Scenes
746 minZ = 8192f; 841 minZ = 8192f;
747 842
748 SceneObjectPart[] parts = m_parts.GetArray(); 843 SceneObjectPart[] parts = m_parts.GetArray();
749 for (int i = 0; i < parts.Length; i++) 844 foreach (SceneObjectPart part in parts)
750 { 845 {
751 SceneObjectPart part = parts[i];
752
753 Vector3 worldPos = part.GetWorldPosition(); 846 Vector3 worldPos = part.GetWorldPosition();
754 Vector3 offset = worldPos - AbsolutePosition; 847 Vector3 offset = worldPos - AbsolutePosition;
755 Quaternion worldRot; 848 Quaternion worldRot;
756 if (part.ParentID == 0) 849 if (part.ParentID == 0)
850 {
757 worldRot = part.RotationOffset; 851 worldRot = part.RotationOffset;
852 }
758 else 853 else
854 {
759 worldRot = part.GetWorldRotation(); 855 worldRot = part.GetWorldRotation();
856 }
760 857
761 Vector3 frontTopLeft; 858 Vector3 frontTopLeft;
762 Vector3 frontTopRight; 859 Vector3 frontTopRight;
@@ -768,6 +865,8 @@ namespace OpenSim.Region.Framework.Scenes
768 Vector3 backBottomLeft; 865 Vector3 backBottomLeft;
769 Vector3 backBottomRight; 866 Vector3 backBottomRight;
770 867
868 // Vector3[] corners = new Vector3[8];
869
771 Vector3 orig = Vector3.Zero; 870 Vector3 orig = Vector3.Zero;
772 871
773 frontTopLeft.X = orig.X - (part.Scale.X / 2); 872 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -802,6 +901,38 @@ namespace OpenSim.Region.Framework.Scenes
802 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 901 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
803 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 902 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
804 903
904
905
906 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
907 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
908 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
909 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
910 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
911 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
912 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
913 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
914
915 //for (int i = 0; i < 8; i++)
916 //{
917 // corners[i] = corners[i] * worldRot;
918 // corners[i] += offset;
919
920 // if (corners[i].X > maxX)
921 // maxX = corners[i].X;
922 // if (corners[i].X < minX)
923 // minX = corners[i].X;
924
925 // if (corners[i].Y > maxY)
926 // maxY = corners[i].Y;
927 // if (corners[i].Y < minY)
928 // minY = corners[i].Y;
929
930 // if (corners[i].Z > maxZ)
931 // maxZ = corners[i].Y;
932 // if (corners[i].Z < minZ)
933 // minZ = corners[i].Z;
934 //}
935
805 frontTopLeft = frontTopLeft * worldRot; 936 frontTopLeft = frontTopLeft * worldRot;
806 frontTopRight = frontTopRight * worldRot; 937 frontTopRight = frontTopRight * worldRot;
807 frontBottomLeft = frontBottomLeft * worldRot; 938 frontBottomLeft = frontBottomLeft * worldRot;
@@ -823,6 +954,15 @@ namespace OpenSim.Region.Framework.Scenes
823 backTopLeft += offset; 954 backTopLeft += offset;
824 backTopRight += offset; 955 backTopRight += offset;
825 956
957 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
958 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
959 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
960 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
961 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
962 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
963 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
964 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
965
826 if (frontTopRight.X > maxX) 966 if (frontTopRight.X > maxX)
827 maxX = frontTopRight.X; 967 maxX = frontTopRight.X;
828 if (frontTopLeft.X > maxX) 968 if (frontTopLeft.X > maxX)
@@ -968,15 +1108,20 @@ namespace OpenSim.Region.Framework.Scenes
968 1108
969 public void SaveScriptedState(XmlTextWriter writer) 1109 public void SaveScriptedState(XmlTextWriter writer)
970 { 1110 {
1111 SaveScriptedState(writer, false);
1112 }
1113
1114 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1115 {
971 XmlDocument doc = new XmlDocument(); 1116 XmlDocument doc = new XmlDocument();
972 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1117 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
973 1118
974 SceneObjectPart[] parts = m_parts.GetArray(); 1119 SceneObjectPart[] parts = m_parts.GetArray();
975 for (int i = 0; i < parts.Length; i++) 1120 for (int i = 0; i < parts.Length; i++)
976 { 1121 {
977 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1122 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
978 foreach (KeyValuePair<UUID, string> kvp in pstates) 1123 foreach (KeyValuePair<UUID, string> kvp in pstates)
979 states.Add(kvp.Key, kvp.Value); 1124 states[kvp.Key] = kvp.Value;
980 } 1125 }
981 1126
982 if (states.Count > 0) 1127 if (states.Count > 0)
@@ -996,6 +1141,168 @@ namespace OpenSim.Region.Framework.Scenes
996 } 1141 }
997 1142
998 /// <summary> 1143 /// <summary>
1144 /// Add the avatar to this linkset (avatar is sat).
1145 /// </summary>
1146 /// <param name="agentID"></param>
1147 public void AddAvatar(UUID agentID)
1148 {
1149 ScenePresence presence;
1150 if (m_scene.TryGetScenePresence(agentID, out presence))
1151 {
1152 if (!m_linkedAvatars.Contains(presence))
1153 {
1154 m_linkedAvatars.Add(presence);
1155 }
1156 }
1157 }
1158
1159 /// <summary>
1160 /// Delete the avatar from this linkset (avatar is unsat).
1161 /// </summary>
1162 /// <param name="agentID"></param>
1163 public void DeleteAvatar(UUID agentID)
1164 {
1165 ScenePresence presence;
1166 if (m_scene.TryGetScenePresence(agentID, out presence))
1167 {
1168 if (m_linkedAvatars.Contains(presence))
1169 {
1170 m_linkedAvatars.Remove(presence);
1171 }
1172 }
1173 }
1174
1175 /// <summary>
1176 /// Returns the list of linked presences (avatars sat on this group)
1177 /// </summary>
1178 /// <param name="agentID"></param>
1179 public List<ScenePresence> GetLinkedAvatars()
1180 {
1181 return m_linkedAvatars;
1182 }
1183
1184 /// <summary>
1185 /// Attach this scene object to the given avatar.
1186 /// </summary>
1187 /// <param name="agentID"></param>
1188 /// <param name="attachmentpoint"></param>
1189 /// <param name="AttachOffset"></param>
1190 private void AttachToAgent(
1191 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1192 {
1193 if (avatar != null)
1194 {
1195 // don't attach attachments to child agents
1196 if (avatar.IsChildAgent) return;
1197
1198 // Remove from database and parcel prim count
1199 m_scene.DeleteFromStorage(so.UUID);
1200 m_scene.EventManager.TriggerParcelPrimCountTainted();
1201
1202 so.AttachedAvatar = avatar.UUID;
1203
1204 if (so.RootPart.PhysActor != null)
1205 {
1206 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1207 so.RootPart.PhysActor = null;
1208 }
1209
1210 so.AbsolutePosition = attachOffset;
1211 so.RootPart.AttachedPos = attachOffset;
1212 so.IsAttachment = true;
1213 so.RootPart.SetParentLocalId(avatar.LocalId);
1214 so.AttachmentPoint = attachmentpoint;
1215
1216 avatar.AddAttachment(this);
1217
1218 if (!silent)
1219 {
1220 // Killing it here will cause the client to deselect it
1221 // It then reappears on the avatar, deselected
1222 // through the full update below
1223 //
1224 if (IsSelected)
1225 {
1226 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1227 }
1228
1229 IsSelected = false; // fudge....
1230 ScheduleGroupForFullUpdate();
1231 }
1232 }
1233 else
1234 {
1235 m_log.WarnFormat(
1236 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1237 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1238 }
1239 }
1240
1241 public byte GetAttachmentPoint()
1242 {
1243 return m_rootPart.Shape.State;
1244 }
1245
1246 public void DetachToGround()
1247 {
1248 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1249 if (avatar == null)
1250 return;
1251
1252 avatar.RemoveAttachment(this);
1253
1254 Vector3 detachedpos = new Vector3(127f,127f,127f);
1255 if (avatar == null)
1256 return;
1257
1258 detachedpos = avatar.AbsolutePosition;
1259 RootPart.FromItemID = UUID.Zero;
1260
1261 AbsolutePosition = detachedpos;
1262 AttachedAvatar = UUID.Zero;
1263
1264 //SceneObjectPart[] parts = m_parts.GetArray();
1265 //for (int i = 0; i < parts.Length; i++)
1266 // parts[i].AttachedAvatar = UUID.Zero;
1267
1268 m_rootPart.SetParentLocalId(0);
1269 AttachmentPoint = (byte)0;
1270 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_scene.m_physicalPrim);
1271 HasGroupChanged = true;
1272 RootPart.Rezzed = DateTime.Now;
1273 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1274 AttachToBackup();
1275 m_scene.EventManager.TriggerParcelPrimCountTainted();
1276 m_rootPart.ScheduleFullUpdate();
1277 m_rootPart.ClearUndoState();
1278 }
1279
1280 public void DetachToInventoryPrep()
1281 {
1282 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1283 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1284 if (avatar != null)
1285 {
1286 //detachedpos = avatar.AbsolutePosition;
1287 avatar.RemoveAttachment(this);
1288 }
1289
1290 AttachedAvatar = UUID.Zero;
1291
1292 /*SceneObjectPart[] parts = m_parts.GetArray();
1293 for (int i = 0; i < parts.Length; i++)
1294 parts[i].AttachedAvatar = UUID.Zero;*/
1295
1296 m_rootPart.SetParentLocalId(0);
1297 //m_rootPart.SetAttachmentPoint((byte)0);
1298 IsAttachment = false;
1299 AbsolutePosition = m_rootPart.AttachedPos;
1300 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1301 //AttachToBackup();
1302 //m_rootPart.ScheduleFullUpdate();
1303 }
1304
1305 /// <summary>
999 /// 1306 ///
1000 /// </summary> 1307 /// </summary>
1001 /// <param name="part"></param> 1308 /// <param name="part"></param>
@@ -1052,7 +1359,10 @@ namespace OpenSim.Region.Framework.Scenes
1052 public void AddPart(SceneObjectPart part) 1359 public void AddPart(SceneObjectPart part)
1053 { 1360 {
1054 part.SetParent(this); 1361 part.SetParent(this);
1055 part.LinkNum = m_parts.Add(part.UUID, part); 1362 m_parts.Add(part.UUID, part);
1363
1364 part.LinkNum = m_parts.Count;
1365
1056 if (part.LinkNum == 2) 1366 if (part.LinkNum == 2)
1057 RootPart.LinkNum = 1; 1367 RootPart.LinkNum = 1;
1058 } 1368 }
@@ -1160,6 +1470,11 @@ namespace OpenSim.Region.Framework.Scenes
1160 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1470 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1161 public void DeleteGroupFromScene(bool silent) 1471 public void DeleteGroupFromScene(bool silent)
1162 { 1472 {
1473 // We need to keep track of this state in case this group is still queued for backup.
1474 IsDeleted = true;
1475
1476 DetachFromBackup();
1477
1163 SceneObjectPart[] parts = m_parts.GetArray(); 1478 SceneObjectPart[] parts = m_parts.GetArray();
1164 for (int i = 0; i < parts.Length; i++) 1479 for (int i = 0; i < parts.Length; i++)
1165 { 1480 {
@@ -1171,17 +1486,19 @@ namespace OpenSim.Region.Framework.Scenes
1171 avatar.StandUp(); 1486 avatar.StandUp();
1172 1487
1173 if (!silent) 1488 if (!silent)
1174 { 1489 {
1175 part.UpdateFlag = 0; 1490 part.UpdateFlag = 0;
1176 if (part == m_rootPart) 1491 if (part == m_rootPart)
1177 { 1492 {
1178 if (!IsAttachment || (AttachedAvatar == avatar.ControllingClient.AgentId) || 1493 if (!IsAttachment || (AttachedAvatar == avatar.ControllingClient.AgentId) ||
1179 (AttachmentPoint < 31) || (AttachmentPoint > 38)) 1494 (AttachmentPoint < 31) || (AttachmentPoint > 38))
1180 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId); 1495 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint>() {part.LocalId});
1181 } 1496 }
1182 } 1497 }
1183 }); 1498 });
1184 } 1499 }
1500
1501
1185 } 1502 }
1186 1503
1187 public void AddScriptLPS(int count) 1504 public void AddScriptLPS(int count)
@@ -1278,7 +1595,12 @@ namespace OpenSim.Region.Framework.Scenes
1278 1595
1279 public void SetOwnerId(UUID userId) 1596 public void SetOwnerId(UUID userId)
1280 { 1597 {
1281 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1598 ForEachPart(delegate(SceneObjectPart part)
1599 {
1600
1601 part.OwnerID = userId;
1602
1603 });
1282 } 1604 }
1283 1605
1284 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1606 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1310,11 +1632,17 @@ namespace OpenSim.Region.Framework.Scenes
1310 return; 1632 return;
1311 } 1633 }
1312 1634
1635 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1636 return;
1637
1313 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1638 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1314 // any exception propogate upwards. 1639 // any exception propogate upwards.
1315 try 1640 try
1316 { 1641 {
1317 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1642 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1643 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1644 m_scene.LoadingPrims) // Land may not be valid yet
1645
1318 { 1646 {
1319 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1647 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1320 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1648 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1341,6 +1669,7 @@ namespace OpenSim.Region.Framework.Scenes
1341 } 1669 }
1342 } 1670 }
1343 } 1671 }
1672
1344 } 1673 }
1345 1674
1346 if (m_scene.UseBackup && HasGroupChanged) 1675 if (m_scene.UseBackup && HasGroupChanged)
@@ -1348,6 +1677,20 @@ namespace OpenSim.Region.Framework.Scenes
1348 // don't backup while it's selected or you're asking for changes mid stream. 1677 // don't backup while it's selected or you're asking for changes mid stream.
1349 if (isTimeToPersist() || forcedBackup) 1678 if (isTimeToPersist() || forcedBackup)
1350 { 1679 {
1680 if (m_rootPart.PhysActor != null &&
1681 (!m_rootPart.PhysActor.IsPhysical))
1682 {
1683 // Possible ghost prim
1684 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1685 {
1686 foreach (SceneObjectPart part in m_parts.GetArray())
1687 {
1688 // Re-set physics actor positions and
1689 // orientations
1690 part.GroupPosition = m_rootPart.GroupPosition;
1691 }
1692 }
1693 }
1351// m_log.DebugFormat( 1694// m_log.DebugFormat(
1352// "[SCENE]: Storing {0}, {1} in {2}", 1695// "[SCENE]: Storing {0}, {1} in {2}",
1353// Name, UUID, m_scene.RegionInfo.RegionName); 1696// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1425,7 +1768,7 @@ namespace OpenSim.Region.Framework.Scenes
1425 // This is only necessary when userExposed is false! 1768 // This is only necessary when userExposed is false!
1426 1769
1427 bool previousAttachmentStatus = dupe.IsAttachment; 1770 bool previousAttachmentStatus = dupe.IsAttachment;
1428 1771
1429 if (!userExposed) 1772 if (!userExposed)
1430 dupe.IsAttachment = true; 1773 dupe.IsAttachment = true;
1431 1774
@@ -1443,11 +1786,11 @@ namespace OpenSim.Region.Framework.Scenes
1443 dupe.m_rootPart.TrimPermissions(); 1786 dupe.m_rootPart.TrimPermissions();
1444 1787
1445 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1788 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1446 1789
1447 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1790 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1448 { 1791 {
1449 return p1.LinkNum.CompareTo(p2.LinkNum); 1792 return p1.LinkNum.CompareTo(p2.LinkNum);
1450 } 1793 }
1451 ); 1794 );
1452 1795
1453 foreach (SceneObjectPart part in partList) 1796 foreach (SceneObjectPart part in partList)
@@ -1467,7 +1810,7 @@ namespace OpenSim.Region.Framework.Scenes
1467 if (part.PhysActor != null && userExposed) 1810 if (part.PhysActor != null && userExposed)
1468 { 1811 {
1469 PrimitiveBaseShape pbs = newPart.Shape; 1812 PrimitiveBaseShape pbs = newPart.Shape;
1470 1813
1471 newPart.PhysActor 1814 newPart.PhysActor
1472 = m_scene.PhysicsScene.AddPrimShape( 1815 = m_scene.PhysicsScene.AddPrimShape(
1473 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1816 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
@@ -1477,11 +1820,11 @@ namespace OpenSim.Region.Framework.Scenes
1477 newPart.RotationOffset, 1820 newPart.RotationOffset,
1478 part.PhysActor.IsPhysical, 1821 part.PhysActor.IsPhysical,
1479 newPart.LocalId); 1822 newPart.LocalId);
1480 1823
1481 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1824 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1482 } 1825 }
1483 } 1826 }
1484 1827
1485 if (userExposed) 1828 if (userExposed)
1486 { 1829 {
1487 dupe.UpdateParentIDs(); 1830 dupe.UpdateParentIDs();
@@ -1596,6 +1939,7 @@ namespace OpenSim.Region.Framework.Scenes
1596 return Vector3.Zero; 1939 return Vector3.Zero;
1597 } 1940 }
1598 1941
1942 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1599 public void moveToTarget(Vector3 target, float tau) 1943 public void moveToTarget(Vector3 target, float tau)
1600 { 1944 {
1601 if (IsAttachment) 1945 if (IsAttachment)
@@ -1623,10 +1967,44 @@ namespace OpenSim.Region.Framework.Scenes
1623 RootPart.PhysActor.PIDActive = false; 1967 RootPart.PhysActor.PIDActive = false;
1624 } 1968 }
1625 1969
1970 public void rotLookAt(Quaternion target, float strength, float damping)
1971 {
1972 SceneObjectPart rootpart = m_rootPart;
1973 if (rootpart != null)
1974 {
1975 if (IsAttachment)
1976 {
1977 /*
1978 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1979 if (avatar != null)
1980 {
1981 Rotate the Av?
1982 } */
1983 }
1984 else
1985 {
1986 if (rootpart.PhysActor != null)
1987 { // APID must be implemented in your physics system for this to function.
1988 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1989 rootpart.PhysActor.APIDStrength = strength;
1990 rootpart.PhysActor.APIDDamping = damping;
1991 rootpart.PhysActor.APIDActive = true;
1992 }
1993 }
1994 }
1995 }
1996
1626 public void stopLookAt() 1997 public void stopLookAt()
1627 { 1998 {
1628 if (RootPart.PhysActor != null) 1999 SceneObjectPart rootpart = m_rootPart;
1629 RootPart.PhysActor.APIDActive = false; 2000 if (rootpart != null)
2001 {
2002 if (rootpart.PhysActor != null)
2003 { // APID must be implemented in your physics system for this to function.
2004 rootpart.PhysActor.APIDActive = false;
2005 }
2006 }
2007
1630 } 2008 }
1631 2009
1632 /// <summary> 2010 /// <summary>
@@ -1684,6 +2062,8 @@ namespace OpenSim.Region.Framework.Scenes
1684 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2062 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1685 { 2063 {
1686 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2064 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2065 newPart.SetParent(this);
2066
1687 AddPart(newPart); 2067 AddPart(newPart);
1688 2068
1689 SetPartAsNonRoot(newPart); 2069 SetPartAsNonRoot(newPart);
@@ -1830,11 +2210,11 @@ namespace OpenSim.Region.Framework.Scenes
1830 /// Immediately send a full update for this scene object. 2210 /// Immediately send a full update for this scene object.
1831 /// </summary> 2211 /// </summary>
1832 public void SendGroupFullUpdate() 2212 public void SendGroupFullUpdate()
1833 { 2213 {
1834 if (IsDeleted) 2214 if (IsDeleted)
1835 return; 2215 return;
1836 2216
1837// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2217// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1838 2218
1839 RootPart.SendFullUpdateToAllClients(); 2219 RootPart.SendFullUpdateToAllClients();
1840 2220
@@ -2030,12 +2410,15 @@ namespace OpenSim.Region.Framework.Scenes
2030 part.LinkNum += objectGroup.PrimCount; 2410 part.LinkNum += objectGroup.PrimCount;
2031 } 2411 }
2032 } 2412 }
2413 }
2033 2414
2034 linkPart.LinkNum = 2; 2415 linkPart.LinkNum = 2;
2035 2416
2036 linkPart.SetParent(this); 2417 linkPart.SetParent(this);
2037 linkPart.CreateSelected = true; 2418 linkPart.CreateSelected = true;
2038 2419
2420 lock (m_parts.SyncRoot)
2421 {
2039 //if (linkPart.PhysActor != null) 2422 //if (linkPart.PhysActor != null)
2040 //{ 2423 //{
2041 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2424 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2193,6 +2576,7 @@ namespace OpenSim.Region.Framework.Scenes
2193 /// <param name="objectGroup"></param> 2576 /// <param name="objectGroup"></param>
2194 public virtual void DetachFromBackup() 2577 public virtual void DetachFromBackup()
2195 { 2578 {
2579 m_scene.SceneGraph.FireDetachFromBackup(this);
2196 if (m_isBackedUp && Scene != null) 2580 if (m_isBackedUp && Scene != null)
2197 m_scene.EventManager.OnBackup -= ProcessBackup; 2581 m_scene.EventManager.OnBackup -= ProcessBackup;
2198 2582
@@ -2211,7 +2595,8 @@ namespace OpenSim.Region.Framework.Scenes
2211 2595
2212 axPos *= parentRot; 2596 axPos *= parentRot;
2213 part.OffsetPosition = axPos; 2597 part.OffsetPosition = axPos;
2214 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2598 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2599 part.GroupPosition = newPos;
2215 part.OffsetPosition = Vector3.Zero; 2600 part.OffsetPosition = Vector3.Zero;
2216 part.RotationOffset = worldRot; 2601 part.RotationOffset = worldRot;
2217 2602
@@ -2222,7 +2607,7 @@ namespace OpenSim.Region.Framework.Scenes
2222 2607
2223 part.LinkNum = linkNum; 2608 part.LinkNum = linkNum;
2224 2609
2225 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2610 part.OffsetPosition = newPos - AbsolutePosition;
2226 2611
2227 Quaternion rootRotation = m_rootPart.RotationOffset; 2612 Quaternion rootRotation = m_rootPart.RotationOffset;
2228 2613
@@ -2232,7 +2617,7 @@ namespace OpenSim.Region.Framework.Scenes
2232 2617
2233 parentRot = m_rootPart.RotationOffset; 2618 parentRot = m_rootPart.RotationOffset;
2234 oldRot = part.RotationOffset; 2619 oldRot = part.RotationOffset;
2235 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2620 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2236 part.RotationOffset = newRot; 2621 part.RotationOffset = newRot;
2237 } 2622 }
2238 2623
@@ -2479,8 +2864,12 @@ namespace OpenSim.Region.Framework.Scenes
2479 } 2864 }
2480 } 2865 }
2481 2866
2867 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, SetVolumeDetect);
2482 for (int i = 0; i < parts.Length; i++) 2868 for (int i = 0; i < parts.Length; i++)
2483 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2869 {
2870 if (parts[i] != RootPart)
2871 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, SetVolumeDetect);
2872 }
2484 } 2873 }
2485 } 2874 }
2486 2875
@@ -2493,6 +2882,17 @@ namespace OpenSim.Region.Framework.Scenes
2493 } 2882 }
2494 } 2883 }
2495 2884
2885
2886
2887 /// <summary>
2888 /// Gets the number of parts
2889 /// </summary>
2890 /// <returns></returns>
2891 public int GetPartCount()
2892 {
2893 return Parts.Count();
2894 }
2895
2496 /// <summary> 2896 /// <summary>
2497 /// Update the texture entry for this part 2897 /// Update the texture entry for this part
2498 /// </summary> 2898 /// </summary>
@@ -2549,7 +2949,6 @@ namespace OpenSim.Region.Framework.Scenes
2549 { 2949 {
2550// m_log.DebugFormat( 2950// m_log.DebugFormat(
2551// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 2951// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2552
2553 RootPart.StoreUndoState(true); 2952 RootPart.StoreUndoState(true);
2554 2953
2555 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 2954 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2650,7 +3049,6 @@ namespace OpenSim.Region.Framework.Scenes
2650 prevScale.X *= x; 3049 prevScale.X *= x;
2651 prevScale.Y *= y; 3050 prevScale.Y *= y;
2652 prevScale.Z *= z; 3051 prevScale.Z *= z;
2653
2654// RootPart.IgnoreUndoUpdate = true; 3052// RootPart.IgnoreUndoUpdate = true;
2655 RootPart.Resize(prevScale); 3053 RootPart.Resize(prevScale);
2656// RootPart.IgnoreUndoUpdate = false; 3054// RootPart.IgnoreUndoUpdate = false;
@@ -2681,7 +3079,9 @@ namespace OpenSim.Region.Framework.Scenes
2681 } 3079 }
2682 3080
2683// obPart.IgnoreUndoUpdate = false; 3081// obPart.IgnoreUndoUpdate = false;
2684// obPart.StoreUndoState(); 3082 HasGroupChanged = true;
3083 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3084 ScheduleGroupForTerseUpdate();
2685 } 3085 }
2686 3086
2687// m_log.DebugFormat( 3087// m_log.DebugFormat(
@@ -2741,9 +3141,9 @@ namespace OpenSim.Region.Framework.Scenes
2741 { 3141 {
2742 SceneObjectPart part = GetChildPart(localID); 3142 SceneObjectPart part = GetChildPart(localID);
2743 3143
2744// SceneObjectPart[] parts = m_parts.GetArray(); 3144 SceneObjectPart[] parts = m_parts.GetArray();
2745// for (int i = 0; i < parts.Length; i++) 3145 for (int i = 0; i < parts.Length; i++)
2746// parts[i].StoreUndoState(); 3146 parts[i].StoreUndoState();
2747 3147
2748 if (part != null) 3148 if (part != null)
2749 { 3149 {
@@ -2799,10 +3199,27 @@ namespace OpenSim.Region.Framework.Scenes
2799 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3199 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2800 } 3200 }
2801 3201
2802 AbsolutePosition = newPos; 3202 //We have to set undoing here because otherwise an undo state will be saved
3203 if (!m_rootPart.Undoing)
3204 {
3205 m_rootPart.Undoing = true;
3206 AbsolutePosition = newPos;
3207 m_rootPart.Undoing = false;
3208 }
3209 else
3210 {
3211 AbsolutePosition = newPos;
3212 }
2803 3213
2804 HasGroupChanged = true; 3214 HasGroupChanged = true;
2805 ScheduleGroupForTerseUpdate(); 3215 if (m_rootPart.Undoing)
3216 {
3217 ScheduleGroupForFullUpdate();
3218 }
3219 else
3220 {
3221 ScheduleGroupForTerseUpdate();
3222 }
2806 } 3223 }
2807 3224
2808 public void OffsetForNewRegion(Vector3 offset) 3225 public void OffsetForNewRegion(Vector3 offset)
@@ -2884,10 +3301,7 @@ namespace OpenSim.Region.Framework.Scenes
2884 public void UpdateSingleRotation(Quaternion rot, uint localID) 3301 public void UpdateSingleRotation(Quaternion rot, uint localID)
2885 { 3302 {
2886 SceneObjectPart part = GetChildPart(localID); 3303 SceneObjectPart part = GetChildPart(localID);
2887
2888 SceneObjectPart[] parts = m_parts.GetArray(); 3304 SceneObjectPart[] parts = m_parts.GetArray();
2889 for (int i = 0; i < parts.Length; i++)
2890 parts[i].StoreUndoState();
2891 3305
2892 if (part != null) 3306 if (part != null)
2893 { 3307 {
@@ -2925,7 +3339,16 @@ namespace OpenSim.Region.Framework.Scenes
2925 if (part.UUID == m_rootPart.UUID) 3339 if (part.UUID == m_rootPart.UUID)
2926 { 3340 {
2927 UpdateRootRotation(rot); 3341 UpdateRootRotation(rot);
2928 AbsolutePosition = pos; 3342 if (!m_rootPart.Undoing)
3343 {
3344 m_rootPart.Undoing = true;
3345 AbsolutePosition = pos;
3346 m_rootPart.Undoing = false;
3347 }
3348 else
3349 {
3350 AbsolutePosition = pos;
3351 }
2929 } 3352 }
2930 else 3353 else
2931 { 3354 {
@@ -2949,9 +3372,10 @@ namespace OpenSim.Region.Framework.Scenes
2949 3372
2950 Quaternion axRot = rot; 3373 Quaternion axRot = rot;
2951 Quaternion oldParentRot = m_rootPart.RotationOffset; 3374 Quaternion oldParentRot = m_rootPart.RotationOffset;
2952
2953 m_rootPart.StoreUndoState(); 3375 m_rootPart.StoreUndoState();
2954 m_rootPart.UpdateRotation(rot); 3376
3377 //Don't use UpdateRotation because it schedules an update prematurely
3378 m_rootPart.RotationOffset = rot;
2955 if (m_rootPart.PhysActor != null) 3379 if (m_rootPart.PhysActor != null)
2956 { 3380 {
2957 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3381 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2966,14 +3390,14 @@ namespace OpenSim.Region.Framework.Scenes
2966 { 3390 {
2967 prim.IgnoreUndoUpdate = true; 3391 prim.IgnoreUndoUpdate = true;
2968 Vector3 axPos = prim.OffsetPosition; 3392 Vector3 axPos = prim.OffsetPosition;
3393
2969 axPos *= oldParentRot; 3394 axPos *= oldParentRot;
2970 axPos *= Quaternion.Inverse(axRot); 3395 axPos *= Quaternion.Inverse(axRot);
2971 prim.OffsetPosition = axPos; 3396 prim.OffsetPosition = axPos;
2972 Quaternion primsRot = prim.RotationOffset; 3397
2973 Quaternion newRot = primsRot * oldParentRot; 3398 prim.RotationOffset *= Quaternion.Inverse(prim.GetWorldRotation()) * (oldParentRot * prim.RotationOffset);
2974 newRot *= Quaternion.Inverse(axRot); 3399
2975 prim.RotationOffset = newRot; 3400 prim.IgnoreUndoUpdate = false;
2976 prim.ScheduleTerseUpdate();
2977 prim.IgnoreUndoUpdate = false; 3401 prim.IgnoreUndoUpdate = false;
2978 } 3402 }
2979 } 3403 }
@@ -2987,8 +3411,8 @@ namespace OpenSim.Region.Framework.Scenes
2987//// childpart.StoreUndoState(); 3411//// childpart.StoreUndoState();
2988// } 3412// }
2989// } 3413// }
2990 3414 HasGroupChanged = true;
2991 m_rootPart.ScheduleTerseUpdate(); 3415 ScheduleGroupForFullUpdate();
2992 3416
2993// m_log.DebugFormat( 3417// m_log.DebugFormat(
2994// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3418// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3216,7 +3640,6 @@ namespace OpenSim.Region.Framework.Scenes
3216 public float GetMass() 3640 public float GetMass()
3217 { 3641 {
3218 float retmass = 0f; 3642 float retmass = 0f;
3219
3220 SceneObjectPart[] parts = m_parts.GetArray(); 3643 SceneObjectPart[] parts = m_parts.GetArray();
3221 for (int i = 0; i < parts.Length; i++) 3644 for (int i = 0; i < parts.Length; i++)
3222 retmass += parts[i].GetMass(); 3645 retmass += parts[i].GetMass();
@@ -3310,6 +3733,14 @@ namespace OpenSim.Region.Framework.Scenes
3310 SetFromItemID(uuid); 3733 SetFromItemID(uuid);
3311 } 3734 }
3312 3735
3736 public void ResetOwnerChangeFlag()
3737 {
3738 ForEachPart(delegate(SceneObjectPart part)
3739 {
3740 part.ResetOwnerChangeFlag();
3741 });
3742 }
3743
3313 #endregion 3744 #endregion
3314 } 3745 }
3315} 3746}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index d631c12..9364b54 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -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
@@ -272,6 +281,7 @@ namespace OpenSim.Region.Framework.Scenes
272 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 281 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
273 private Vector3 m_sitTargetPosition; 282 private Vector3 m_sitTargetPosition;
274 private string m_sitAnimation = "SIT"; 283 private string m_sitAnimation = "SIT";
284 private bool m_occupied; // KF if any av is sitting on this prim
275 private string m_text = String.Empty; 285 private string m_text = String.Empty;
276 private string m_touchName = String.Empty; 286 private string m_touchName = String.Empty;
277 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 287 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
@@ -315,6 +325,7 @@ namespace OpenSim.Region.Framework.Scenes
315 protected Vector3 m_lastAcceleration; 325 protected Vector3 m_lastAcceleration;
316 protected Vector3 m_lastAngularVelocity; 326 protected Vector3 m_lastAngularVelocity;
317 protected int m_lastTerseSent; 327 protected int m_lastTerseSent;
328 protected float m_buoyancy = 0.0f;
318 329
319 /// <summary> 330 /// <summary>
320 /// Stores media texture data 331 /// Stores media texture data
@@ -367,7 +378,7 @@ namespace OpenSim.Region.Framework.Scenes
367 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 378 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
368 Quaternion rotationOffset, Vector3 offsetPosition) 379 Quaternion rotationOffset, Vector3 offsetPosition)
369 { 380 {
370 m_name = "Primitive"; 381 m_name = "Object";
371 382
372 Rezzed = DateTime.UtcNow; 383 Rezzed = DateTime.UtcNow;
373 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 384 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
@@ -422,7 +433,7 @@ namespace OpenSim.Region.Framework.Scenes
422 private uint _ownerMask = (uint)PermissionMask.All; 433 private uint _ownerMask = (uint)PermissionMask.All;
423 private uint _groupMask = (uint)PermissionMask.None; 434 private uint _groupMask = (uint)PermissionMask.None;
424 private uint _everyoneMask = (uint)PermissionMask.None; 435 private uint _everyoneMask = (uint)PermissionMask.None;
425 private uint _nextOwnerMask = (uint)PermissionMask.All; 436 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
426 private PrimFlags _flags = PrimFlags.None; 437 private PrimFlags _flags = PrimFlags.None;
427 private DateTime m_expires; 438 private DateTime m_expires;
428 private DateTime m_rezzed; 439 private DateTime m_rezzed;
@@ -521,12 +532,16 @@ namespace OpenSim.Region.Framework.Scenes
521 } 532 }
522 533
523 /// <value> 534 /// <value>
524 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 535 /// Get the inventory list
525 /// </value> 536 /// </value>
526 public TaskInventoryDictionary TaskInventory 537 public TaskInventoryDictionary TaskInventory
527 { 538 {
528 get { return m_inventory.Items; } 539 get {
529 set { m_inventory.Items = value; } 540 return m_inventory.Items;
541 }
542 set {
543 m_inventory.Items = value;
544 }
530 } 545 }
531 546
532 /// <summary> 547 /// <summary>
@@ -667,14 +682,12 @@ namespace OpenSim.Region.Framework.Scenes
667 set { m_LoopSoundSlavePrims = value; } 682 set { m_LoopSoundSlavePrims = value; }
668 } 683 }
669 684
670
671 public Byte[] TextureAnimation 685 public Byte[] TextureAnimation
672 { 686 {
673 get { return m_TextureAnimation; } 687 get { return m_TextureAnimation; }
674 set { m_TextureAnimation = value; } 688 set { m_TextureAnimation = value; }
675 } 689 }
676 690
677
678 public Byte[] ParticleSystem 691 public Byte[] ParticleSystem
679 { 692 {
680 get { return m_particleSystem; } 693 get { return m_particleSystem; }
@@ -711,9 +724,11 @@ namespace OpenSim.Region.Framework.Scenes
711 { 724 {
712 // If this is a linkset, we don't want the physics engine mucking up our group position here. 725 // If this is a linkset, we don't want the physics engine mucking up our group position here.
713 PhysicsActor actor = PhysActor; 726 PhysicsActor actor = PhysActor;
714 if (actor != null && _parentID == 0) 727 if (_parentID == 0)
715 { 728 {
716 m_groupPosition = actor.Position; 729 if (actor != null)
730 m_groupPosition = actor.Position;
731 return m_groupPosition;
717 } 732 }
718 733
719 if (m_parentGroup.IsAttachment) 734 if (m_parentGroup.IsAttachment)
@@ -723,12 +738,14 @@ namespace OpenSim.Region.Framework.Scenes
723 return sp.AbsolutePosition; 738 return sp.AbsolutePosition;
724 } 739 }
725 740
741 // use root prim's group position. Physics may have updated it
742 if (ParentGroup.RootPart != this)
743 m_groupPosition = ParentGroup.RootPart.GroupPosition;
726 return m_groupPosition; 744 return m_groupPosition;
727 } 745 }
728 set 746 set
729 { 747 {
730 m_groupPosition = value; 748 m_groupPosition = value;
731
732 PhysicsActor actor = PhysActor; 749 PhysicsActor actor = PhysActor;
733 if (actor != null) 750 if (actor != null)
734 { 751 {
@@ -748,22 +765,13 @@ namespace OpenSim.Region.Framework.Scenes
748 765
749 // Tell the physics engines that this prim changed. 766 // Tell the physics engines that this prim changed.
750 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 767 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
768
751 } 769 }
752 catch (Exception e) 770 catch (Exception e)
753 { 771 {
754 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 772 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
755 } 773 }
756 } 774 }
757
758 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
759 if (m_sitTargetAvatar != UUID.Zero)
760 {
761 ScenePresence avatar;
762 if (m_parentGroup.Scene.TryGetScenePresence(m_sitTargetAvatar, out avatar))
763 {
764 avatar.ParentPosition = GetWorldPosition();
765 }
766 }
767 } 775 }
768 } 776 }
769 777
@@ -772,7 +780,7 @@ namespace OpenSim.Region.Framework.Scenes
772 get { return m_offsetPosition; } 780 get { return m_offsetPosition; }
773 set 781 set
774 { 782 {
775// StoreUndoState(); 783 Vector3 oldpos = m_offsetPosition;
776 m_offsetPosition = value; 784 m_offsetPosition = value;
777 785
778 if (ParentGroup != null && !ParentGroup.IsDeleted) 786 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -787,7 +795,22 @@ namespace OpenSim.Region.Framework.Scenes
787 if (m_parentGroup.Scene != null) 795 if (m_parentGroup.Scene != null)
788 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 796 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
789 } 797 }
798
799 if (!m_parentGroup.m_dupeInProgress)
800 {
801 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
802 foreach (ScenePresence av in avs)
803 {
804 if (av.LinkedPrim == m_uuid)
805 {
806 Vector3 offset = (m_offsetPosition - oldpos);
807 av.AbsolutePosition += offset;
808 av.SendAvatarDataToAllAgents();
809 }
810 }
811 }
790 } 812 }
813 TriggerScriptChangedEvent(Changed.POSITION);
791 } 814 }
792 } 815 }
793 816
@@ -914,7 +937,16 @@ namespace OpenSim.Region.Framework.Scenes
914 /// <summary></summary> 937 /// <summary></summary>
915 public Vector3 Acceleration 938 public Vector3 Acceleration
916 { 939 {
917 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
918 set { m_acceleration = value; } 950 set { m_acceleration = value; }
919 } 951 }
920 952
@@ -1245,6 +1277,13 @@ namespace OpenSim.Region.Framework.Scenes
1245 _flags = value; 1277 _flags = value;
1246 } 1278 }
1247 } 1279 }
1280
1281 [XmlIgnore]
1282 public bool IsOccupied // KF If an av is sittingon this prim
1283 {
1284 get { return m_occupied; }
1285 set { m_occupied = value; }
1286 }
1248 1287
1249 1288
1250 public UUID SitTargetAvatar 1289 public UUID SitTargetAvatar
@@ -1303,6 +1342,19 @@ namespace OpenSim.Region.Framework.Scenes
1303 set { m_collisionSoundVolume = value; } 1342 set { m_collisionSoundVolume = value; }
1304 } 1343 }
1305 1344
1345 public float Buoyancy
1346 {
1347 get { return m_buoyancy; }
1348 set
1349 {
1350 m_buoyancy = value;
1351 if (PhysActor != null)
1352 {
1353 PhysActor.Buoyancy = value;
1354 }
1355 }
1356 }
1357
1306 #endregion Public Properties with only Get 1358 #endregion Public Properties with only Get
1307 1359
1308 private uint ApplyMask(uint val, bool set, uint mask) 1360 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1672,6 +1724,9 @@ namespace OpenSim.Region.Framework.Scenes
1672 1724
1673 // Move afterwards ResetIDs as it clears the localID 1725 // Move afterwards ResetIDs as it clears the localID
1674 dupe.LocalId = localID; 1726 dupe.LocalId = localID;
1727 if(dupe.PhysActor != null)
1728 dupe.PhysActor.LocalID = localID;
1729
1675 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1730 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1676 dupe._lastOwnerID = OwnerID; 1731 dupe._lastOwnerID = OwnerID;
1677 1732
@@ -2035,19 +2090,17 @@ namespace OpenSim.Region.Framework.Scenes
2035 public Vector3 GetWorldPosition() 2090 public Vector3 GetWorldPosition()
2036 { 2091 {
2037 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2092 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2038
2039 Vector3 axPos = OffsetPosition; 2093 Vector3 axPos = OffsetPosition;
2040
2041 axPos *= parentRot; 2094 axPos *= parentRot;
2042 Vector3 translationOffsetPosition = axPos; 2095 Vector3 translationOffsetPosition = axPos;
2043 2096 if(_parentID == 0)
2044// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name); 2097 {
2045 2098 return GroupPosition;
2046 Vector3 worldPos = GroupPosition + translationOffsetPosition; 2099 }
2047 2100 else
2048// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name); 2101 {
2049 2102 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2050 return worldPos; 2103 }
2051 } 2104 }
2052 2105
2053 /// <summary> 2106 /// <summary>
@@ -2687,17 +2740,18 @@ namespace OpenSim.Region.Framework.Scenes
2687 //Trys to fetch sound id from prim's inventory. 2740 //Trys to fetch sound id from prim's inventory.
2688 //Prim's inventory doesn't support non script items yet 2741 //Prim's inventory doesn't support non script items yet
2689 2742
2690 lock (TaskInventory) 2743 TaskInventory.LockItemsForRead(true);
2744
2745 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2691 { 2746 {
2692 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2747 if (item.Value.Name == sound)
2693 { 2748 {
2694 if (item.Value.Name == sound) 2749 soundID = item.Value.ItemID;
2695 { 2750 break;
2696 soundID = item.Value.ItemID;
2697 break;
2698 }
2699 } 2751 }
2700 } 2752 }
2753
2754 TaskInventory.LockItemsForRead(false);
2701 } 2755 }
2702 2756
2703 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2757 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2782,7 +2836,7 @@ namespace OpenSim.Region.Framework.Scenes
2782 2836
2783 public void RotLookAt(Quaternion target, float strength, float damping) 2837 public void RotLookAt(Quaternion target, float strength, float damping)
2784 { 2838 {
2785 rotLookAt(target, strength, damping); 2839 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2786 } 2840 }
2787 2841
2788 public void rotLookAt(Quaternion target, float strength, float damping) 2842 public void rotLookAt(Quaternion target, float strength, float damping)
@@ -3027,8 +3081,8 @@ namespace OpenSim.Region.Framework.Scenes
3027 { 3081 {
3028 const float ROTATION_TOLERANCE = 0.01f; 3082 const float ROTATION_TOLERANCE = 0.01f;
3029 const float VELOCITY_TOLERANCE = 0.001f; 3083 const float VELOCITY_TOLERANCE = 0.001f;
3030 const float POSITION_TOLERANCE = 0.05f; 3084 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3031 const int TIME_MS_TOLERANCE = 3000; 3085 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3032 3086
3033 if (m_updateFlag == 1) 3087 if (m_updateFlag == 1)
3034 { 3088 {
@@ -3042,7 +3096,7 @@ namespace OpenSim.Region.Framework.Scenes
3042 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3096 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3043 { 3097 {
3044 AddTerseUpdateToAllAvatars(); 3098 AddTerseUpdateToAllAvatars();
3045 ClearUpdateSchedule(); 3099
3046 3100
3047 // This causes the Scene to 'poll' physical objects every couple of frames 3101 // This causes the Scene to 'poll' physical objects every couple of frames
3048 // bad, so it's been replaced by an event driven method. 3102 // bad, so it's been replaced by an event driven method.
@@ -3060,16 +3114,18 @@ namespace OpenSim.Region.Framework.Scenes
3060 m_lastAngularVelocity = AngularVelocity; 3114 m_lastAngularVelocity = AngularVelocity;
3061 m_lastTerseSent = Environment.TickCount; 3115 m_lastTerseSent = Environment.TickCount;
3062 } 3116 }
3117 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3118 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3063 } 3119 }
3064 else 3120 else
3065 { 3121 {
3066 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3122 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3067 { 3123 {
3068 AddFullUpdateToAllAvatars(); 3124 AddFullUpdateToAllAvatars();
3069 ClearUpdateSchedule(); 3125 m_updateFlag = 0; //Same here
3070 } 3126 }
3071 } 3127 }
3072 ClearUpdateSchedule(); 3128 m_updateFlag = 0;
3073 } 3129 }
3074 3130
3075 /// <summary> 3131 /// <summary>
@@ -3097,17 +3153,16 @@ namespace OpenSim.Region.Framework.Scenes
3097 if (!UUID.TryParse(sound, out soundID)) 3153 if (!UUID.TryParse(sound, out soundID))
3098 { 3154 {
3099 // search sound file from inventory 3155 // search sound file from inventory
3100 lock (TaskInventory) 3156 TaskInventory.LockItemsForRead(true);
3157 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3101 { 3158 {
3102 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3159 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3103 { 3160 {
3104 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3161 soundID = item.Value.ItemID;
3105 { 3162 break;
3106 soundID = item.Value.ItemID;
3107 break;
3108 }
3109 } 3163 }
3110 } 3164 }
3165 TaskInventory.LockItemsForRead(false);
3111 } 3166 }
3112 3167
3113 if (soundID == UUID.Zero) 3168 if (soundID == UUID.Zero)
@@ -3518,7 +3573,7 @@ namespace OpenSim.Region.Framework.Scenes
3518 3573
3519 public void StopLookAt() 3574 public void StopLookAt()
3520 { 3575 {
3521 m_parentGroup.stopLookAt(); 3576 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3522 3577
3523 m_parentGroup.ScheduleGroupForTerseUpdate(); 3578 m_parentGroup.ScheduleGroupForTerseUpdate();
3524 } 3579 }
@@ -3569,45 +3624,45 @@ namespace OpenSim.Region.Framework.Scenes
3569 // TODO: May need to fix for group comparison 3624 // TODO: May need to fix for group comparison
3570 if (last.Compare(this)) 3625 if (last.Compare(this))
3571 { 3626 {
3572 // m_log.DebugFormat( 3627 // m_log.DebugFormat(
3573 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3628 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3574 // Name, LocalId, m_undo.Count); 3629 // Name, LocalId, m_undo.Count);
3575 3630
3576 return; 3631 return;
3577 } 3632 }
3578 } 3633 }
3579 } 3634 }
3580 3635
3581 // m_log.DebugFormat( 3636 // m_log.DebugFormat(
3582 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", 3637 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3583 // Name, LocalId, forGroup, m_undo.Count); 3638 // Name, LocalId, forGroup, m_undo.Count);
3584 3639
3585 if (m_parentGroup.GetSceneMaxUndo() > 0) 3640 if (m_parentGroup.GetSceneMaxUndo() > 0)
3586 { 3641 {
3587 UndoState nUndo = new UndoState(this, forGroup); 3642 UndoState nUndo = new UndoState(this, forGroup);
3588 3643
3589 m_undo.Push(nUndo); 3644 m_undo.Push(nUndo);
3590 3645
3591 if (m_redo.Count > 0) 3646 if (m_redo.Count > 0)
3592 m_redo.Clear(); 3647 m_redo.Clear();
3593 3648
3594 // m_log.DebugFormat( 3649 // m_log.DebugFormat(
3595 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3650 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3596 // Name, LocalId, forGroup, m_undo.Count); 3651 // Name, LocalId, forGroup, m_undo.Count);
3597 } 3652 }
3598 } 3653 }
3599 } 3654 }
3600 } 3655 }
3601// else 3656 // else
3602// { 3657 // {
3603// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3658 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3604// } 3659 // }
3605 } 3660 }
3606// else 3661 // else
3607// { 3662 // {
3608// m_log.DebugFormat( 3663 // m_log.DebugFormat(
3609// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3664 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3610// } 3665 // }
3611 } 3666 }
3612 3667
3613 /// <summary> 3668 /// <summary>
@@ -4657,8 +4712,9 @@ namespace OpenSim.Region.Framework.Scenes
4657 { 4712 {
4658 m_shape.TextureEntry = textureEntry; 4713 m_shape.TextureEntry = textureEntry;
4659 TriggerScriptChangedEvent(Changed.TEXTURE); 4714 TriggerScriptChangedEvent(Changed.TEXTURE);
4660 4715 m_updateFlag = 1;
4661 ParentGroup.HasGroupChanged = true; 4716 ParentGroup.HasGroupChanged = true;
4717
4662 //This is madness.. 4718 //This is madness..
4663 //ParentGroup.ScheduleGroupForFullUpdate(); 4719 //ParentGroup.ScheduleGroupForFullUpdate();
4664 //This is sparta 4720 //This is sparta
@@ -4850,5 +4906,17 @@ namespace OpenSim.Region.Framework.Scenes
4850 Color color = Color; 4906 Color color = Color;
4851 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4907 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4852 } 4908 }
4909
4910 public void ResetOwnerChangeFlag()
4911 {
4912 List<UUID> inv = Inventory.GetInventoryList();
4913
4914 foreach (UUID itemID in inv)
4915 {
4916 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4917 item.OwnerChanged = false;
4918 Inventory.UpdateInventoryItem(item, false, false);
4919 }
4920 }
4853 } 4921 }
4854} 4922}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 9446741..4edc220 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,11 +87,14 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -123,38 +129,45 @@ namespace OpenSim.Region.Framework.Scenes
123 public void ResetInventoryIDs() 129 public void ResetInventoryIDs()
124 { 130 {
125 if (null == m_part) 131 if (null == m_part)
126 return; 132 m_items.LockItemsForWrite(true);
127 133
128 lock (m_items) 134 if (Items.Count == 0)
129 { 135 {
130 if (0 == m_items.Count) 136 m_items.LockItemsForWrite(false);
131 return; 137 return;
138 }
132 139
133 IList<TaskInventoryItem> items = GetInventoryItems(); 140 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
134 m_items.Clear(); 141 Items.Clear();
135 142
136 foreach (TaskInventoryItem item in items) 143 foreach (TaskInventoryItem item in items)
137 { 144 {
138 item.ResetIDs(m_part.UUID); 145 item.ResetIDs(m_part.UUID);
139 m_items.Add(item.ItemID, item); 146 Items.Add(item.ItemID, item);
140 }
141 } 147 }
148 m_items.LockItemsForWrite(false);
142 } 149 }
143 150
144 public void ResetObjectID() 151 public void ResetObjectID()
145 { 152 {
146 lock (Items) 153 m_items.LockItemsForWrite(true);
154
155 if (Items.Count == 0)
147 { 156 {
148 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 m_items.LockItemsForWrite(false);
149 Items.Clear(); 158 return;
150
151 foreach (TaskInventoryItem item in items)
152 {
153 item.ParentPartID = m_part.UUID;
154 item.ParentID = m_part.UUID;
155 Items.Add(item.ItemID, item);
156 }
157 } 159 }
160
161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
162 Items.Clear();
163
164 foreach (TaskInventoryItem item in items)
165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
169 }
170 m_items.LockItemsForWrite(false);
158 } 171 }
159 172
160 /// <summary> 173 /// <summary>
@@ -163,12 +176,11 @@ namespace OpenSim.Region.Framework.Scenes
163 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
164 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
165 { 178 {
166 lock (Items) 179 m_items.LockItemsForWrite(true);
180 if (0 == Items.Count)
167 { 181 {
168 if (0 == Items.Count) 182 m_items.LockItemsForWrite(false);
169 { 183 return;
170 return;
171 }
172 } 184 }
173 185
174 HasInventoryChanged = true; 186 HasInventoryChanged = true;
@@ -184,6 +196,7 @@ namespace OpenSim.Region.Framework.Scenes
184 item.PermsGranter = UUID.Zero; 196 item.PermsGranter = UUID.Zero;
185 item.OwnerChanged = true; 197 item.OwnerChanged = true;
186 } 198 }
199 m_items.LockItemsForWrite(false);
187 } 200 }
188 201
189 /// <summary> 202 /// <summary>
@@ -192,12 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
192 /// <param name="groupID"></param> 205 /// <param name="groupID"></param>
193 public void ChangeInventoryGroup(UUID groupID) 206 public void ChangeInventoryGroup(UUID groupID)
194 { 207 {
195 lock (Items) 208 m_items.LockItemsForWrite(true);
209 if (0 == Items.Count)
196 { 210 {
197 if (0 == Items.Count) 211 m_items.LockItemsForWrite(false);
198 { 212 return;
199 return;
200 }
201 } 213 }
202 214
203 // Don't let this set the HasGroupChanged flag for attachments 215 // Don't let this set the HasGroupChanged flag for attachments
@@ -209,12 +221,45 @@ namespace OpenSim.Region.Framework.Scenes
209 m_part.ParentGroup.HasGroupChanged = true; 221 m_part.ParentGroup.HasGroupChanged = true;
210 } 222 }
211 223
212 List<TaskInventoryItem> items = GetInventoryItems(); 224 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
213 foreach (TaskInventoryItem item in items) 225 foreach (TaskInventoryItem item in items)
214 { 226 {
215 if (groupID != item.GroupID) 227 if (groupID != item.GroupID)
228 {
216 item.GroupID = groupID; 229 item.GroupID = groupID;
230 }
217 } 231 }
232 m_items.LockItemsForWrite(false);
233 }
234
235 private void QueryScriptStates()
236 {
237 if (m_part == null || m_part.ParentGroup == null)
238 return;
239
240 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
241 if (engines == null) // No engine at all
242 return;
243
244 Items.LockItemsForRead(true);
245 foreach (TaskInventoryItem item in Items.Values)
246 {
247 if (item.InvType == (int)InventoryType.LSL)
248 {
249 foreach (IScriptModule e in engines)
250 {
251 bool running;
252
253 if (e.HasScript(item.ItemID, out running))
254 {
255 item.ScriptRunning = running;
256 break;
257 }
258 }
259 }
260 }
261
262 Items.LockItemsForRead(false);
218 } 263 }
219 264
220 /// <summary> 265 /// <summary>
@@ -222,9 +267,14 @@ namespace OpenSim.Region.Framework.Scenes
222 /// </summary> 267 /// </summary>
223 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
224 { 269 {
225 List<TaskInventoryItem> scripts = GetInventoryScripts(); 270 Items.LockItemsForRead(true);
226 foreach (TaskInventoryItem item in scripts) 271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
227 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 272 Items.LockItemsForRead(false);
273 foreach (TaskInventoryItem item in items)
274 {
275 if ((int)InventoryType.LSL == item.InvType)
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
277 }
228 } 278 }
229 279
230 public ArrayList GetScriptErrors(UUID itemID) 280 public ArrayList GetScriptErrors(UUID itemID)
@@ -257,9 +307,18 @@ namespace OpenSim.Region.Framework.Scenes
257 /// </param> 307 /// </param>
258 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 308 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
259 { 309 {
260 List<TaskInventoryItem> scripts = GetInventoryScripts(); 310 Items.LockItemsForRead(true);
261 foreach (TaskInventoryItem item in scripts) 311 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
262 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 312 Items.LockItemsForRead(false);
313
314 foreach (TaskInventoryItem item in items)
315 {
316 if ((int)InventoryType.LSL == item.InvType)
317 {
318 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
319 m_part.RemoveScriptEvents(item.ItemID);
320 }
321 }
263 } 322 }
264 323
265 /// <summary> 324 /// <summary>
@@ -275,7 +334,10 @@ namespace OpenSim.Region.Framework.Scenes
275 // item.Name, item.ItemID, Name, UUID); 334 // item.Name, item.ItemID, Name, UUID);
276 335
277 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 336 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
337 {
338 StoreScriptError(item.ItemID, "no permission");
278 return; 339 return;
340 }
279 341
280 m_part.AddFlag(PrimFlags.Scripted); 342 m_part.AddFlag(PrimFlags.Scripted);
281 343
@@ -284,14 +346,13 @@ namespace OpenSim.Region.Framework.Scenes
284 if (stateSource == 2 && // Prim crossing 346 if (stateSource == 2 && // Prim crossing
285 m_part.ParentGroup.Scene.m_trustBinaries) 347 m_part.ParentGroup.Scene.m_trustBinaries)
286 { 348 {
287 lock (m_items) 349 m_items.LockItemsForWrite(true);
288 { 350 m_items[item.ItemID].PermsMask = 0;
289 m_items[item.ItemID].PermsMask = 0; 351 m_items[item.ItemID].PermsGranter = UUID.Zero;
290 m_items[item.ItemID].PermsGranter = UUID.Zero; 352 m_items.LockItemsForWrite(false);
291 }
292
293 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 353 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
294 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 354 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
355 StoreScriptErrors(item.ItemID, null);
295 m_part.ParentGroup.AddActiveScriptCount(1); 356 m_part.ParentGroup.AddActiveScriptCount(1);
296 m_part.ScheduleFullUpdate(); 357 m_part.ScheduleFullUpdate();
297 return; 358 return;
@@ -300,6 +361,8 @@ namespace OpenSim.Region.Framework.Scenes
300 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 361 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
301 if (null == asset) 362 if (null == asset)
302 { 363 {
364 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
365 StoreScriptError(item.ItemID, msg);
303 m_log.ErrorFormat( 366 m_log.ErrorFormat(
304 "[PRIM INVENTORY]: " + 367 "[PRIM INVENTORY]: " +
305 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 368 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -311,15 +374,20 @@ namespace OpenSim.Region.Framework.Scenes
311 if (m_part.ParentGroup.m_savedScriptState != null) 374 if (m_part.ParentGroup.m_savedScriptState != null)
312 RestoreSavedScriptState(item.OldItemID, item.ItemID); 375 RestoreSavedScriptState(item.OldItemID, item.ItemID);
313 376
314 lock (m_items) 377 m_items.LockItemsForWrite(true);
315 { 378
316 m_items[item.ItemID].PermsMask = 0; 379 m_items[item.ItemID].PermsMask = 0;
317 m_items[item.ItemID].PermsGranter = UUID.Zero; 380 m_items[item.ItemID].PermsGranter = UUID.Zero;
318 } 381
382 m_items.LockItemsForWrite(false);
319 383
320 string script = Utils.BytesToString(asset.Data); 384 string script = Utils.BytesToString(asset.Data);
321 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 385 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
322 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 386 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
387 StoreScriptErrors(item.ItemID, null);
388 if (!item.ScriptRunning)
389 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
390 m_part.LocalId, item.ItemID);
323 m_part.ParentGroup.AddActiveScriptCount(1); 391 m_part.ParentGroup.AddActiveScriptCount(1);
324 m_part.ScheduleFullUpdate(); 392 m_part.ScheduleFullUpdate();
325 } 393 }
@@ -383,21 +451,145 @@ namespace OpenSim.Region.Framework.Scenes
383 451
384 /// <summary> 452 /// <summary>
385 /// Start a script which is in this prim's inventory. 453 /// Start a script which is in this prim's inventory.
454 /// Some processing may occur in the background, but this routine returns asap.
386 /// </summary> 455 /// </summary>
387 /// <param name="itemId"> 456 /// <param name="itemId">
388 /// A <see cref="UUID"/> 457 /// A <see cref="UUID"/>
389 /// </param> 458 /// </param>
390 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 459 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
391 { 460 {
392 TaskInventoryItem item = GetInventoryItem(itemId); 461 lock (m_scriptErrors)
393 if (item != null) 462 {
394 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 463 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
464 m_scriptErrors.Remove(itemId);
465 }
466 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
467 }
468
469 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
470 {
471 m_items.LockItemsForRead(true);
472 if (m_items.ContainsKey(itemId))
473 {
474 if (m_items.ContainsKey(itemId))
475 {
476 m_items.LockItemsForRead(false);
477 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
478 }
479 else
480 {
481 m_items.LockItemsForRead(false);
482 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
483 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
484 StoreScriptError(itemId, msg);
485 m_log.ErrorFormat(
486 "[PRIM INVENTORY]: " +
487 "Couldn't start script with ID {0} since it {1}", itemId, msg);
488 }
489 }
395 else 490 else
491 {
492 m_items.LockItemsForRead(false);
493 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
494 StoreScriptError(itemId, msg);
396 m_log.ErrorFormat( 495 m_log.ErrorFormat(
397 "[PRIM INVENTORY]: " + 496 "[PRIM INVENTORY]: " +
398 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 497 "Couldn't start script with ID {0} since it {1}", itemId, msg);
399 itemId, m_part.Name, m_part.UUID, 498 }
400 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 499
500 }
501
502 /// <summary>
503 /// Start a script which is in this prim's inventory and return any compilation error messages.
504 /// </summary>
505 /// <param name="itemId">
506 /// A <see cref="UUID"/>
507 /// </param>
508 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
509 {
510 ArrayList errors;
511
512 // Indicate to CreateScriptInstanceInternal() we want it to
513 // post any compilation/loading error messages
514 lock (m_scriptErrors)
515 {
516 m_scriptErrors[itemId] = null;
517 }
518
519 // Perform compilation/loading
520 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
521
522 // Wait for and retrieve any errors
523 lock (m_scriptErrors)
524 {
525 while ((errors = m_scriptErrors[itemId]) == null)
526 {
527 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
528 {
529 m_log.ErrorFormat(
530 "[PRIM INVENTORY]: " +
531 "timedout waiting for script {0} errors", itemId);
532 errors = m_scriptErrors[itemId];
533 if (errors == null)
534 {
535 errors = new ArrayList(1);
536 errors.Add("timedout waiting for errors");
537 }
538 break;
539 }
540 }
541 m_scriptErrors.Remove(itemId);
542 }
543 return errors;
544 }
545
546 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
547 private void StoreScriptErrors(UUID itemId, ArrayList errors)
548 {
549 lock (m_scriptErrors)
550 {
551 // If compilation/loading initiated via CreateScriptInstance(),
552 // it does not want the errors, so just get out
553 if (!m_scriptErrors.ContainsKey(itemId))
554 {
555 return;
556 }
557
558 // Initiated via CreateScriptInstanceEr(), if we know what the
559 // errors are, save them and wake CreateScriptInstanceEr().
560 if (errors != null)
561 {
562 m_scriptErrors[itemId] = errors;
563 System.Threading.Monitor.PulseAll(m_scriptErrors);
564 return;
565 }
566 }
567
568 // Initiated via CreateScriptInstanceEr() but we don't know what
569 // the errors are yet, so retrieve them from the script engine.
570 // This may involve some waiting internal to GetScriptErrors().
571 errors = GetScriptErrors(itemId);
572
573 // Get a default non-null value to indicate success.
574 if (errors == null)
575 {
576 errors = new ArrayList();
577 }
578
579 // Post to CreateScriptInstanceEr() and wake it up
580 lock (m_scriptErrors)
581 {
582 m_scriptErrors[itemId] = errors;
583 System.Threading.Monitor.PulseAll(m_scriptErrors);
584 }
585 }
586
587 // Like StoreScriptErrors(), but just posts a single string message
588 private void StoreScriptError(UUID itemId, string message)
589 {
590 ArrayList errors = new ArrayList(1);
591 errors.Add(message);
592 StoreScriptErrors(itemId, errors);
401 } 593 }
402 594
403 /// <summary> 595 /// <summary>
@@ -410,15 +602,7 @@ namespace OpenSim.Region.Framework.Scenes
410 /// </param> 602 /// </param>
411 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 603 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
412 { 604 {
413 bool scriptPresent = false; 605 if (m_items.ContainsKey(itemId))
414
415 lock (m_items)
416 {
417 if (m_items.ContainsKey(itemId))
418 scriptPresent = true;
419 }
420
421 if (scriptPresent)
422 { 606 {
423 if (!sceneObjectBeingDeleted) 607 if (!sceneObjectBeingDeleted)
424 m_part.RemoveScriptEvents(itemId); 608 m_part.RemoveScriptEvents(itemId);
@@ -443,14 +627,16 @@ namespace OpenSim.Region.Framework.Scenes
443 /// <returns></returns> 627 /// <returns></returns>
444 private bool InventoryContainsName(string name) 628 private bool InventoryContainsName(string name)
445 { 629 {
446 lock (m_items) 630 m_items.LockItemsForRead(true);
631 foreach (TaskInventoryItem item in m_items.Values)
447 { 632 {
448 foreach (TaskInventoryItem item in m_items.Values) 633 if (item.Name == name)
449 { 634 {
450 if (item.Name == name) 635 m_items.LockItemsForRead(false);
451 return true; 636 return true;
452 } 637 }
453 } 638 }
639 m_items.LockItemsForRead(false);
454 return false; 640 return false;
455 } 641 }
456 642
@@ -492,8 +678,9 @@ namespace OpenSim.Region.Framework.Scenes
492 /// <param name="item"></param> 678 /// <param name="item"></param>
493 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 679 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
494 { 680 {
495 List<TaskInventoryItem> il = GetInventoryItems(); 681 m_items.LockItemsForRead(true);
496 682 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
683 m_items.LockItemsForRead(false);
497 foreach (TaskInventoryItem i in il) 684 foreach (TaskInventoryItem i in il)
498 { 685 {
499 if (i.Name == item.Name) 686 if (i.Name == item.Name)
@@ -531,14 +718,14 @@ namespace OpenSim.Region.Framework.Scenes
531 item.Name = name; 718 item.Name = name;
532 item.GroupID = m_part.GroupID; 719 item.GroupID = m_part.GroupID;
533 720
534 lock (m_items) 721 m_items.LockItemsForWrite(true);
535 m_items.Add(item.ItemID, item); 722 m_items.Add(item.ItemID, item);
536 723 m_items.LockItemsForWrite(false);
537 if (allowedDrop) 724 if (allowedDrop)
538 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 725 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
539 else 726 else
540 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 727 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
541 728
542 m_inventorySerial++; 729 m_inventorySerial++;
543 //m_inventorySerial += 2; 730 //m_inventorySerial += 2;
544 HasInventoryChanged = true; 731 HasInventoryChanged = true;
@@ -554,15 +741,15 @@ namespace OpenSim.Region.Framework.Scenes
554 /// <param name="items"></param> 741 /// <param name="items"></param>
555 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 742 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
556 { 743 {
557 lock (m_items) 744 m_items.LockItemsForWrite(true);
745 foreach (TaskInventoryItem item in items)
558 { 746 {
559 foreach (TaskInventoryItem item in items) 747 m_items.Add(item.ItemID, item);
560 { 748// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
561 m_items.Add(item.ItemID, item);
562// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
563 }
564 m_inventorySerial++;
565 } 749 }
750 m_items.LockItemsForWrite(false);
751
752 m_inventorySerial++;
566 } 753 }
567 754
568 /// <summary> 755 /// <summary>
@@ -573,10 +760,9 @@ namespace OpenSim.Region.Framework.Scenes
573 public TaskInventoryItem GetInventoryItem(UUID itemId) 760 public TaskInventoryItem GetInventoryItem(UUID itemId)
574 { 761 {
575 TaskInventoryItem item; 762 TaskInventoryItem item;
576 763 m_items.LockItemsForRead(true);
577 lock (m_items) 764 m_items.TryGetValue(itemId, out item);
578 m_items.TryGetValue(itemId, out item); 765 m_items.LockItemsForRead(false);
579
580 return item; 766 return item;
581 } 767 }
582 768
@@ -592,15 +778,16 @@ namespace OpenSim.Region.Framework.Scenes
592 { 778 {
593 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 779 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
594 780
595 lock (m_items) 781 m_items.LockItemsForRead(true);
782
783 foreach (TaskInventoryItem item in m_items.Values)
596 { 784 {
597 foreach (TaskInventoryItem item in m_items.Values) 785 if (item.Name == name)
598 { 786 items.Add(item);
599 if (item.Name == name)
600 items.Add(item);
601 }
602 } 787 }
603 788
789 m_items.LockItemsForRead(false);
790
604 return items; 791 return items;
605 } 792 }
606 793
@@ -619,6 +806,9 @@ namespace OpenSim.Region.Framework.Scenes
619 string xmlData = Utils.BytesToString(rezAsset.Data); 806 string xmlData = Utils.BytesToString(rezAsset.Data);
620 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 807 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
621 808
809 group.RootPart.AttachPoint = group.RootPart.Shape.State;
810 group.RootPart.AttachOffset = group.AbsolutePosition;
811
622 group.ResetIDs(); 812 group.ResetIDs();
623 813
624 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 814 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -693,8 +883,9 @@ namespace OpenSim.Region.Framework.Scenes
693 883
694 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 884 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
695 { 885 {
696 TaskInventoryItem it = GetInventoryItem(item.ItemID); 886 m_items.LockItemsForWrite(true);
697 if (it != null) 887
888 if (m_items.ContainsKey(item.ItemID))
698 { 889 {
699// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 890// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
700 891
@@ -707,14 +898,10 @@ namespace OpenSim.Region.Framework.Scenes
707 item.GroupID = m_part.GroupID; 898 item.GroupID = m_part.GroupID;
708 899
709 if (item.AssetID == UUID.Zero) 900 if (item.AssetID == UUID.Zero)
710 item.AssetID = it.AssetID; 901 item.AssetID = m_items[item.ItemID].AssetID;
711 902
712 lock (m_items) 903 m_items[item.ItemID] = item;
713 { 904 m_inventorySerial++;
714 m_items[item.ItemID] = item;
715 m_inventorySerial++;
716 }
717
718 if (fireScriptEvents) 905 if (fireScriptEvents)
719 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 906 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
720 907
@@ -723,7 +910,7 @@ namespace OpenSim.Region.Framework.Scenes
723 HasInventoryChanged = true; 910 HasInventoryChanged = true;
724 m_part.ParentGroup.HasGroupChanged = true; 911 m_part.ParentGroup.HasGroupChanged = true;
725 } 912 }
726 913 m_items.LockItemsForWrite(false);
727 return true; 914 return true;
728 } 915 }
729 else 916 else
@@ -734,8 +921,9 @@ namespace OpenSim.Region.Framework.Scenes
734 item.ItemID, m_part.Name, m_part.UUID, 921 item.ItemID, m_part.Name, m_part.UUID,
735 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 922 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
736 } 923 }
737 return false; 924 m_items.LockItemsForWrite(false);
738 925
926 return false;
739 } 927 }
740 928
741 /// <summary> 929 /// <summary>
@@ -746,43 +934,59 @@ namespace OpenSim.Region.Framework.Scenes
746 /// in this prim's inventory.</returns> 934 /// in this prim's inventory.</returns>
747 public int RemoveInventoryItem(UUID itemID) 935 public int RemoveInventoryItem(UUID itemID)
748 { 936 {
749 TaskInventoryItem item = GetInventoryItem(itemID); 937 m_items.LockItemsForRead(true);
750 if (item != null) 938
939 if (m_items.ContainsKey(itemID))
751 { 940 {
752 int type = m_items[itemID].InvType; 941 int type = m_items[itemID].InvType;
942 m_items.LockItemsForRead(false);
753 if (type == 10) // Script 943 if (type == 10) // Script
754 { 944 {
755 m_part.RemoveScriptEvents(itemID);
756 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 945 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
757 } 946 }
947 m_items.LockItemsForWrite(true);
758 m_items.Remove(itemID); 948 m_items.Remove(itemID);
949 m_items.LockItemsForWrite(false);
759 m_inventorySerial++; 950 m_inventorySerial++;
760 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 951 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
761 952
762 HasInventoryChanged = true; 953 HasInventoryChanged = true;
763 m_part.ParentGroup.HasGroupChanged = true; 954 m_part.ParentGroup.HasGroupChanged = true;
764 955
765 if (!ContainsScripts()) 956 int scriptcount = 0;
957 m_items.LockItemsForRead(true);
958 foreach (TaskInventoryItem item in m_items.Values)
959 {
960 if (item.Type == 10)
961 {
962 scriptcount++;
963 }
964 }
965 m_items.LockItemsForRead(false);
966
967
968 if (scriptcount <= 0)
969 {
766 m_part.RemFlag(PrimFlags.Scripted); 970 m_part.RemFlag(PrimFlags.Scripted);
971 }
767 972
768 m_part.ScheduleFullUpdate(); 973 m_part.ScheduleFullUpdate();
769 974
770 return type; 975 return type;
771
772 } 976 }
773 else 977 else
774 { 978 {
979 m_items.LockItemsForRead(false);
775 m_log.ErrorFormat( 980 m_log.ErrorFormat(
776 "[PRIM INVENTORY]: " + 981 "[PRIM INVENTORY]: " +
777 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 982 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
778 itemID, m_part.Name, m_part.UUID, 983 itemID, m_part.Name, m_part.UUID);
779 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
780 } 984 }
781 985
782 return -1; 986 return -1;
783 } 987 }
784 988
785 private bool CreateInventoryFile() 989 private bool CreateInventoryFileName()
786 { 990 {
787// m_log.DebugFormat( 991// m_log.DebugFormat(
788// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 992// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -791,116 +995,124 @@ namespace OpenSim.Region.Framework.Scenes
791 if (m_inventoryFileName == String.Empty || 995 if (m_inventoryFileName == String.Empty ||
792 m_inventoryFileNameSerial < m_inventorySerial) 996 m_inventoryFileNameSerial < m_inventorySerial)
793 { 997 {
794 // Something changed, we need to create a new file
795 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 998 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
796 m_inventoryFileNameSerial = m_inventorySerial; 999 m_inventoryFileNameSerial = m_inventorySerial;
797 1000
798 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1001 return true;
1002 }
1003
1004 return false;
1005 }
1006
1007 /// <summary>
1008 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1009 /// </summary>
1010 /// <param name="xferManager"></param>
1011 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1012 {
1013 bool changed = CreateInventoryFileName();
1014
1015 bool includeAssets = false;
1016 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1017 includeAssets = true;
1018
1019 if (m_inventoryPrivileged != includeAssets)
1020 changed = true;
1021
1022 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1023
1024 Items.LockItemsForRead(true);
1025
1026 if (m_inventorySerial == 0) // No inventory
1027 {
1028 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1029 Items.LockItemsForRead(false);
1030 return;
1031 }
799 1032
800 lock (m_items) 1033 if (m_items.Count == 0) // No inventory
1034 {
1035 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1036 return;
1037 }
1038
1039 if (!changed)
1040 {
1041 if (m_inventoryFileData.Length > 2)
801 { 1042 {
802 foreach (TaskInventoryItem item in m_items.Values) 1043 xferManager.AddNewFile(m_inventoryFileName,
803 { 1044 m_inventoryFileData);
804// m_log.DebugFormat( 1045 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
805// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1046 Util.StringToBytes256(m_inventoryFileName));
806// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
807 1047
808 UUID ownerID = item.OwnerID; 1048 Items.LockItemsForRead(false);
809 uint everyoneMask = 0; 1049 return;
810 uint baseMask = item.BasePermissions; 1050 }
811 uint ownerMask = item.CurrentPermissions; 1051 }
812 uint groupMask = item.GroupPermissions;
813 1052
814 invString.AddItemStart(); 1053 m_inventoryPrivileged = includeAssets;
815 invString.AddNameValueLine("item_id", item.ItemID.ToString());
816 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
817 1054
818 invString.AddPermissionsStart(); 1055 foreach (TaskInventoryItem item in m_items.Values)
1056 {
1057 UUID ownerID = item.OwnerID;
1058 uint everyoneMask = 0;
1059 uint baseMask = item.BasePermissions;
1060 uint ownerMask = item.CurrentPermissions;
1061 uint groupMask = item.GroupPermissions;
819 1062
820 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1063 invString.AddItemStart();
821 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1064 invString.AddNameValueLine("item_id", item.ItemID.ToString());
822 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1065 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
823 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
824 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
825 1066
826 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1067 invString.AddPermissionsStart();
827 invString.AddNameValueLine("owner_id", ownerID.ToString());
828 1068
829 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1069 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1070 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1071 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1072 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1073 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
830 1074
831 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1075 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
832 invString.AddSectionEnd(); 1076 invString.AddNameValueLine("owner_id", ownerID.ToString());
833 1077
834 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1078 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
835 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
836 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
837 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
838 1079
839 invString.AddSaleStart(); 1080 invString.AddNameValueLine("group_id", item.GroupID.ToString());
840 invString.AddNameValueLine("sale_type", "not"); 1081 invString.AddSectionEnd();
841 invString.AddNameValueLine("sale_price", "0");
842 invString.AddSectionEnd();
843 1082
844 invString.AddNameValueLine("name", item.Name + "|"); 1083 if (includeAssets)
845 invString.AddNameValueLine("desc", item.Description + "|"); 1084 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1085 else
1086 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1087 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
1088 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
1089 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
846 1090
847 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1091 invString.AddSaleStart();
848 invString.AddSectionEnd(); 1092 invString.AddNameValueLine("sale_type", "not");
849 } 1093 invString.AddNameValueLine("sale_price", "0");
850 } 1094 invString.AddSectionEnd();
851 1095
852 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1096 invString.AddNameValueLine("name", item.Name + "|");
1097 invString.AddNameValueLine("desc", item.Description + "|");
853 1098
854 return true; 1099 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1100 invString.AddSectionEnd();
855 } 1101 }
856 1102
857 // No need to recreate, the existing file is fine 1103 Items.LockItemsForRead(false);
858 return false;
859 }
860 1104
861 /// <summary> 1105 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
862 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
863 /// </summary>
864 /// <param name="xferManager"></param>
865 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
866 {
867 lock (m_items)
868 {
869 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
870 // a new script if any previous deletion has left the prim inventory empty.
871 if (m_items.Count == 0) // No inventory
872 {
873// m_log.DebugFormat(
874// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
875// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
876 1106
877 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1107 if (m_inventoryFileData.Length > 2)
878 return; 1108 {
879 } 1109 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
880 1110 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
881 CreateInventoryFile(); 1111 Util.StringToBytes256(m_inventoryFileName));
882 1112 return;
883 // In principle, we should only do the rest if the inventory changed;
884 // by sending m_inventorySerial to the client, it ought to know
885 // that nothing changed and that it doesn't need to request the file.
886 // Unfortunately, it doesn't look like the client optimizes this;
887 // the client seems to always come back and request the Xfer,
888 // no matter what value m_inventorySerial has.
889 // FIXME: Could probably be > 0 here rather than > 2
890 if (m_inventoryFileData.Length > 2)
891 {
892 // Add the file for Xfer
893 // m_log.DebugFormat(
894 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
895 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
896
897 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
898 }
899
900 // Tell the client we're ready to Xfer the file
901 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
902 Util.StringToBytes256(m_inventoryFileName));
903 } 1113 }
1114
1115 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
904 } 1116 }
905 1117
906 /// <summary> 1118 /// <summary>
@@ -911,10 +1123,11 @@ namespace OpenSim.Region.Framework.Scenes
911 { 1123 {
912 if (HasInventoryChanged) 1124 if (HasInventoryChanged)
913 { 1125 {
914 HasInventoryChanged = false; 1126 Items.LockItemsForRead(true);
915 List<TaskInventoryItem> items = GetInventoryItems(); 1127 datastore.StorePrimInventory(m_part.UUID, Items.Values);
916 datastore.StorePrimInventory(m_part.UUID, items); 1128 Items.LockItemsForRead(false);
917 1129
1130 HasInventoryChanged = false;
918 } 1131 }
919 } 1132 }
920 1133
@@ -981,82 +1194,63 @@ namespace OpenSim.Region.Framework.Scenes
981 { 1194 {
982 uint mask=0x7fffffff; 1195 uint mask=0x7fffffff;
983 1196
984 lock (m_items) 1197 foreach (TaskInventoryItem item in m_items.Values)
985 { 1198 {
986 foreach (TaskInventoryItem item in m_items.Values) 1199 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1200 mask &= ~((uint)PermissionMask.Copy >> 13);
1201 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1202 mask &= ~((uint)PermissionMask.Transfer >> 13);
1203 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1204 mask &= ~((uint)PermissionMask.Modify >> 13);
1205
1206 if (item.InvType == (int)InventoryType.Object)
987 { 1207 {
988 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1208 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
989 mask &= ~((uint)PermissionMask.Copy >> 13); 1209 mask &= ~((uint)PermissionMask.Copy >> 13);
990 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1210 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
991 mask &= ~((uint)PermissionMask.Transfer >> 13); 1211 mask &= ~((uint)PermissionMask.Transfer >> 13);
992 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1212 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
993 mask &= ~((uint)PermissionMask.Modify >> 13); 1213 mask &= ~((uint)PermissionMask.Modify >> 13);
994
995 if (item.InvType != (int)InventoryType.Object)
996 {
997 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
998 mask &= ~((uint)PermissionMask.Copy >> 13);
999 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1000 mask &= ~((uint)PermissionMask.Transfer >> 13);
1001 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1002 mask &= ~((uint)PermissionMask.Modify >> 13);
1003 }
1004 else
1005 {
1006 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1007 mask &= ~((uint)PermissionMask.Copy >> 13);
1008 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1009 mask &= ~((uint)PermissionMask.Transfer >> 13);
1010 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1011 mask &= ~((uint)PermissionMask.Modify >> 13);
1012 }
1013
1014 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1015 mask &= ~(uint)PermissionMask.Copy;
1016 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1017 mask &= ~(uint)PermissionMask.Transfer;
1018 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1019 mask &= ~(uint)PermissionMask.Modify;
1020 } 1214 }
1215
1216 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1217 mask &= ~(uint)PermissionMask.Copy;
1218 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1219 mask &= ~(uint)PermissionMask.Transfer;
1220 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1221 mask &= ~(uint)PermissionMask.Modify;
1021 } 1222 }
1022
1023 return mask; 1223 return mask;
1024 } 1224 }
1025 1225
1026 public void ApplyNextOwnerPermissions() 1226 public void ApplyNextOwnerPermissions()
1027 { 1227 {
1028 lock (m_items) 1228 foreach (TaskInventoryItem item in m_items.Values)
1029 { 1229 {
1030 foreach (TaskInventoryItem item in m_items.Values) 1230 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1031 { 1231 {
1032 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1232 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1033 { 1233 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1034 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1234 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1035 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1235 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1036 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1236 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1037 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1237 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1038 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1039 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1040 }
1041 item.CurrentPermissions &= item.NextPermissions;
1042 item.BasePermissions &= item.NextPermissions;
1043 item.EveryonePermissions &= item.NextPermissions;
1044 item.OwnerChanged = true;
1045 item.PermsMask = 0;
1046 item.PermsGranter = UUID.Zero;
1047 } 1238 }
1239 item.OwnerChanged = true;
1240 item.CurrentPermissions &= item.NextPermissions;
1241 item.BasePermissions &= item.NextPermissions;
1242 item.EveryonePermissions &= item.NextPermissions;
1243 item.PermsMask = 0;
1244 item.PermsGranter = UUID.Zero;
1048 } 1245 }
1049 } 1246 }
1050 1247
1051 public void ApplyGodPermissions(uint perms) 1248 public void ApplyGodPermissions(uint perms)
1052 { 1249 {
1053 lock (m_items) 1250 foreach (TaskInventoryItem item in m_items.Values)
1054 { 1251 {
1055 foreach (TaskInventoryItem item in m_items.Values) 1252 item.CurrentPermissions = perms;
1056 { 1253 item.BasePermissions = perms;
1057 item.CurrentPermissions = perms;
1058 item.BasePermissions = perms;
1059 }
1060 } 1254 }
1061 1255
1062 m_inventorySerial++; 1256 m_inventorySerial++;
@@ -1069,17 +1263,13 @@ namespace OpenSim.Region.Framework.Scenes
1069 /// <returns></returns> 1263 /// <returns></returns>
1070 public bool ContainsScripts() 1264 public bool ContainsScripts()
1071 { 1265 {
1072 lock (m_items) 1266 foreach (TaskInventoryItem item in m_items.Values)
1073 { 1267 {
1074 foreach (TaskInventoryItem item in m_items.Values) 1268 if (item.InvType == (int)InventoryType.LSL)
1075 { 1269 {
1076 if (item.InvType == (int)InventoryType.LSL) 1270 return true;
1077 {
1078 return true;
1079 }
1080 } 1271 }
1081 } 1272 }
1082
1083 return false; 1273 return false;
1084 } 1274 }
1085 1275
@@ -1087,11 +1277,8 @@ namespace OpenSim.Region.Framework.Scenes
1087 { 1277 {
1088 List<UUID> ret = new List<UUID>(); 1278 List<UUID> ret = new List<UUID>();
1089 1279
1090 lock (m_items) 1280 foreach (TaskInventoryItem item in m_items.Values)
1091 { 1281 ret.Add(item.ItemID);
1092 foreach (TaskInventoryItem item in m_items.Values)
1093 ret.Add(item.ItemID);
1094 }
1095 1282
1096 return ret; 1283 return ret;
1097 } 1284 }
@@ -1122,6 +1309,11 @@ namespace OpenSim.Region.Framework.Scenes
1122 1309
1123 public Dictionary<UUID, string> GetScriptStates() 1310 public Dictionary<UUID, string> GetScriptStates()
1124 { 1311 {
1312 return GetScriptStates(false);
1313 }
1314
1315 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1316 {
1125 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1317 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1126 1318
1127 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1319 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1132,25 +1324,35 @@ namespace OpenSim.Region.Framework.Scenes
1132 if (engines == null) // No engine at all 1324 if (engines == null) // No engine at all
1133 return ret; 1325 return ret;
1134 1326
1135 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1327 Items.LockItemsForRead(true);
1136 1328 foreach (TaskInventoryItem item in m_items.Values)
1137 foreach (TaskInventoryItem item in scripts)
1138 { 1329 {
1139 foreach (IScriptModule e in engines) 1330 if (item.InvType == (int)InventoryType.LSL)
1140 { 1331 {
1141 if (e != null) 1332 foreach (IScriptModule e in engines)
1142 { 1333 {
1143 string n = e.GetXMLState(item.ItemID); 1334 if (e != null)
1144 if (n != String.Empty)
1145 { 1335 {
1146 if (!ret.ContainsKey(item.ItemID)) 1336 string n = e.GetXMLState(item.ItemID);
1147 ret[item.ItemID] = n; 1337 if (n != String.Empty)
1148 break; 1338 {
1339 if (oldIDs)
1340 {
1341 if (!ret.ContainsKey(item.OldItemID))
1342 ret[item.OldItemID] = n;
1343 }
1344 else
1345 {
1346 if (!ret.ContainsKey(item.ItemID))
1347 ret[item.ItemID] = n;
1348 }
1349 break;
1350 }
1149 } 1351 }
1150 } 1352 }
1151 } 1353 }
1152 } 1354 }
1153 1355 Items.LockItemsForRead(false);
1154 return ret; 1356 return ret;
1155 } 1357 }
1156 1358
@@ -1160,21 +1362,27 @@ namespace OpenSim.Region.Framework.Scenes
1160 if (engines == null) 1362 if (engines == null)
1161 return; 1363 return;
1162 1364
1163 List<TaskInventoryItem> scripts = GetInventoryScripts();
1164 1365
1165 foreach (TaskInventoryItem item in scripts) 1366 Items.LockItemsForRead(true);
1367
1368 foreach (TaskInventoryItem item in m_items.Values)
1166 { 1369 {
1167 foreach (IScriptModule engine in engines) 1370 if (item.InvType == (int)InventoryType.LSL)
1168 { 1371 {
1169 if (engine != null) 1372 foreach (IScriptModule engine in engines)
1170 { 1373 {
1171 if (item.OwnerChanged) 1374 if (engine != null)
1172 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1375 {
1173 item.OwnerChanged = false; 1376 if (item.OwnerChanged)
1174 engine.ResumeScript(item.ItemID); 1377 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1378 item.OwnerChanged = false;
1379 engine.ResumeScript(item.ItemID);
1380 }
1175 } 1381 }
1176 } 1382 }
1177 } 1383 }
1384
1385 Items.LockItemsForRead(false);
1178 } 1386 }
1179 } 1387 }
1180} 1388}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 5b02c3b..e0ec7c9 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("[SCENE PRESENCE] Destructor called"); 74// m_log.Debug("[SCENE PRESENCE] 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 public PresenceType PresenceType { get; private set; } 79 public PresenceType PresenceType { get; private set; }
@@ -89,7 +90,9 @@ namespace OpenSim.Region.Framework.Scenes
89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 90 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
90 /// issue #1716 91 /// issue #1716
91 /// </summary> 92 /// </summary>
92 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 93// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
94 // Value revised by KF 091121 by comparison with SL.
95 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
93 96
94 /// <summary> 97 /// <summary>
95 /// Movement updates for agents in neighboring regions are sent directly to clients. 98 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -118,6 +121,7 @@ namespace OpenSim.Region.Framework.Scenes
118 /// TODO: For some reason, we effectively have a list both here and in Appearance. Need to work out if this is 121 /// TODO: For some reason, we effectively have a list both here and in Appearance. Need to work out if this is
119 /// necessary. 122 /// necessary.
120 /// </remarks> 123 /// </remarks>
124
121 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>(); 125 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
122 126
123 public Object AttachmentsSyncLock { get; private set; } 127 public Object AttachmentsSyncLock { get; private set; }
@@ -131,8 +135,11 @@ namespace OpenSim.Region.Framework.Scenes
131 public Vector3 lastKnownAllowedPosition; 135 public Vector3 lastKnownAllowedPosition;
132 public bool sentMessageAboutRestrictedParcelFlyingDown; 136 public bool sentMessageAboutRestrictedParcelFlyingDown;
133 public Vector4 CollisionPlane = Vector4.UnitW; 137 public Vector4 CollisionPlane = Vector4.UnitW;
134 138
139 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
140 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
135 private Vector3 m_lastPosition; 141 private Vector3 m_lastPosition;
142 private Vector3 m_lastWorldPosition;
136 private Quaternion m_lastRotation; 143 private Quaternion m_lastRotation;
137 private Vector3 m_lastVelocity; 144 private Vector3 m_lastVelocity;
138 //private int m_lastTerseSent; 145 //private int m_lastTerseSent;
@@ -140,6 +147,11 @@ namespace OpenSim.Region.Framework.Scenes
140 private bool m_updateflag; 147 private bool m_updateflag;
141 private byte m_movementflag; 148 private byte m_movementflag;
142 private Vector3? m_forceToApply; 149 private Vector3? m_forceToApply;
150 private int m_userFlags;
151 public int UserFlags
152 {
153 get { return m_userFlags; }
154 }
143 private TeleportFlags m_teleportFlags; 155 private TeleportFlags m_teleportFlags;
144 public TeleportFlags TeleportFlags 156 public TeleportFlags TeleportFlags
145 { 157 {
@@ -170,9 +182,10 @@ namespace OpenSim.Region.Framework.Scenes
170 private int m_perfMonMS; 182 private int m_perfMonMS;
171 183
172 private bool m_setAlwaysRun; 184 private bool m_setAlwaysRun;
173
174 private bool m_forceFly; 185 private bool m_forceFly;
175 private bool m_flyDisabled; 186 private bool m_flyDisabled;
187 private bool m_flyingOld; // add for fly velocity control
188 public bool m_wasFlying; // add for fly velocity control
176 189
177 private float m_speedModifier = 1.0f; 190 private float m_speedModifier = 1.0f;
178 191
@@ -188,7 +201,8 @@ namespace OpenSim.Region.Framework.Scenes
188 201
189 protected ulong crossingFromRegion; 202 protected ulong crossingFromRegion;
190 203
191 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 204 private readonly Vector3[] Dir_Vectors = new Vector3[11];
205 private bool m_isNudging = false;
192 206
193 // Position of agent's camera in world (region cordinates) 207 // Position of agent's camera in world (region cordinates)
194 protected Vector3 m_CameraCenter; 208 protected Vector3 m_CameraCenter;
@@ -213,12 +227,14 @@ namespace OpenSim.Region.Framework.Scenes
213 private bool m_autopilotMoving; 227 private bool m_autopilotMoving;
214 private Vector3 m_autoPilotTarget; 228 private Vector3 m_autoPilotTarget;
215 private bool m_sitAtAutoTarget; 229 private bool m_sitAtAutoTarget;
230 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
216 231
217 private string m_nextSitAnimation = String.Empty; 232 private string m_nextSitAnimation = String.Empty;
218 233
219 //PauPaw:Proper PID Controler for autopilot************ 234 //PauPaw:Proper PID Controler for autopilot************
220 public bool MovingToTarget { get; private set; } 235 public bool MovingToTarget { get; private set; }
221 public Vector3 MoveToPositionTarget { get; private set; } 236 public Vector3 MoveToPositionTarget { get; private set; }
237 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
222 238
223 /// <summary> 239 /// <summary>
224 /// Controls whether an avatar automatically moving to a target will land when it gets there (if flying). 240 /// Controls whether an avatar automatically moving to a target will land when it gets there (if flying).
@@ -228,7 +244,13 @@ namespace OpenSim.Region.Framework.Scenes
228 private bool m_followCamAuto; 244 private bool m_followCamAuto;
229 245
230 private int m_movementUpdateCount; 246 private int m_movementUpdateCount;
247 private int m_lastColCount = -1; //KF: Look for Collision chnages
248 private int m_updateCount = 0; //KF: Update Anims for a while
249 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
231 private const int NumMovementsBetweenRayCast = 5; 250 private const int NumMovementsBetweenRayCast = 5;
251 private List<uint> m_lastColliders = new List<uint>();
252
253 private object m_syncRoot = new Object();
232 254
233 private bool CameraConstraintActive; 255 private bool CameraConstraintActive;
234 //private int m_moveToPositionStateStatus; 256 //private int m_moveToPositionStateStatus;
@@ -265,7 +287,9 @@ namespace OpenSim.Region.Framework.Scenes
265 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 287 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
266 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 288 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
267 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 289 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
268 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 290 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
291 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
292 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
269 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 293 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
270 } 294 }
271 295
@@ -469,8 +493,9 @@ namespace OpenSim.Region.Framework.Scenes
469 get 493 get
470 { 494 {
471 PhysicsActor actor = m_physicsActor; 495 PhysicsActor actor = m_physicsActor;
472 if (actor != null) 496// if (actor != null)
473 { 497 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
498 {
474 m_pos = actor.Position; 499 m_pos = actor.Position;
475 500
476// m_log.DebugFormat( 501// m_log.DebugFormat(
@@ -497,7 +522,7 @@ namespace OpenSim.Region.Framework.Scenes
497 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 522 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
498 if (part != null) 523 if (part != null)
499 { 524 {
500 return m_parentPosition + (m_pos * part.GetWorldRotation()); 525 return part.AbsolutePosition + (m_pos * part.GetWorldRotation());
501 } 526 }
502 else 527 else
503 { 528 {
@@ -524,7 +549,9 @@ namespace OpenSim.Region.Framework.Scenes
524 } 549 }
525 } 550 }
526 551
527 m_pos = value; 552// Changed this to update unconditionally to make npose work
553// if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
554 m_pos = value;
528 m_parentPosition = Vector3.Zero; 555 m_parentPosition = Vector3.Zero;
529 556
530// m_log.DebugFormat( 557// m_log.DebugFormat(
@@ -585,13 +612,38 @@ namespace OpenSim.Region.Framework.Scenes
585 } 612 }
586 } 613 }
587 614
615 public Quaternion OffsetRotation
616 {
617 get { return m_offsetRotation; }
618 set { m_offsetRotation = value; }
619 }
620
588 public Quaternion Rotation 621 public Quaternion Rotation
589 { 622 {
590 get { return m_bodyRot; } 623 get {
591 set 624 if (m_parentID != 0)
592 { 625 {
626 if (m_offsetRotation != null)
627 {
628 return m_offsetRotation;
629 }
630 else
631 {
632 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
633 }
634
635 }
636 else
637 {
638 return m_bodyRot;
639 }
640 }
641 set {
593 m_bodyRot = value; 642 m_bodyRot = value;
594// m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot); 643 if (m_parentID != 0)
644 {
645 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
646 }
595 } 647 }
596 } 648 }
597 649
@@ -611,11 +663,21 @@ namespace OpenSim.Region.Framework.Scenes
611 663
612 private uint m_parentID; 664 private uint m_parentID;
613 665
666
667 private UUID m_linkedPrim;
668
614 public uint ParentID 669 public uint ParentID
615 { 670 {
616 get { return m_parentID; } 671 get { return m_parentID; }
617 set { m_parentID = value; } 672 set { m_parentID = value; }
618 } 673 }
674
675 public UUID LinkedPrim
676 {
677 get { return m_linkedPrim; }
678 set { m_linkedPrim = value; }
679 }
680
619 public float Health 681 public float Health
620 { 682 {
621 get { return m_health; } 683 get { return m_health; }
@@ -751,6 +813,7 @@ namespace OpenSim.Region.Framework.Scenes
751 m_localId = m_scene.AllocateLocalId(); 813 m_localId = m_scene.AllocateLocalId();
752 814
753 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 815 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
816 m_userFlags = account.UserFlags;
754 817
755 if (account != null) 818 if (account != null)
756 m_userLevel = account.UserLevel; 819 m_userLevel = account.UserLevel;
@@ -769,10 +832,7 @@ namespace OpenSim.Region.Framework.Scenes
769 m_reprioritization_timer.AutoReset = false; 832 m_reprioritization_timer.AutoReset = false;
770 833
771 AdjustKnownSeeds(); 834 AdjustKnownSeeds();
772
773 // TODO: I think, this won't send anything, as we are still a child here...
774 Animator.TrySetMovementAnimation("STAND"); 835 Animator.TrySetMovementAnimation("STAND");
775
776 // we created a new ScenePresence (a new child agent) in a fresh region. 836 // we created a new ScenePresence (a new child agent) in a fresh region.
777 // Request info about all the (root) agents in this region 837 // Request info about all the (root) agents in this region
778 // Note: This won't send data *to* other clients in that region (children don't send) 838 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -813,25 +873,47 @@ namespace OpenSim.Region.Framework.Scenes
813 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 873 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
814 Dir_Vectors[4] = Vector3.UnitZ; //UP 874 Dir_Vectors[4] = Vector3.UnitZ; //UP
815 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 875 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
816 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 876 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
817 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 877 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
818 Dir_Vectors[7] = -Vector3.UnitX; //BACK 878 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
879 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
880 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
819 } 881 }
820 882
821 private Vector3[] GetWalkDirectionVectors() 883 private Vector3[] GetWalkDirectionVectors()
822 { 884 {
823 Vector3[] vector = new Vector3[9]; 885 Vector3[] vector = new Vector3[11];
824 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 886 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
825 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 887 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
826 vector[2] = Vector3.UnitY; //LEFT 888 vector[2] = Vector3.UnitY; //LEFT
827 vector[3] = -Vector3.UnitY; //RIGHT 889 vector[3] = -Vector3.UnitY; //RIGHT
828 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 890 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
829 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 891 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
830 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 892 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
831 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 893 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
832 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 894 vector[8] = Vector3.UnitY; //LEFT_NUDGE
895 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
896 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
833 return vector; 897 return vector;
834 } 898 }
899
900 private bool[] GetDirectionIsNudge()
901 {
902 bool[] isNudge = new bool[11];
903 isNudge[0] = false; //FORWARD
904 isNudge[1] = false; //BACK
905 isNudge[2] = false; //LEFT
906 isNudge[3] = false; //RIGHT
907 isNudge[4] = false; //UP
908 isNudge[5] = false; //DOWN
909 isNudge[6] = true; //FORWARD_NUDGE
910 isNudge[7] = true; //BACK_NUDGE
911 isNudge[8] = true; //LEFT_NUDGE
912 isNudge[9] = true; //RIGHT_NUDGE
913 isNudge[10] = true; //DOWN_Nudge
914 return isNudge;
915 }
916
835 917
836 #endregion 918 #endregion
837 919
@@ -896,6 +978,62 @@ namespace OpenSim.Region.Framework.Scenes
896 pos.Y = crossedBorder.BorderLine.Z - 1; 978 pos.Y = crossedBorder.BorderLine.Z - 1;
897 } 979 }
898 980
981 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
982 if (land != null)
983 {
984 // If we come in via login, landmark or map, we want to
985 // honor landing points. If we come in via Lure, we want
986 // to ignore them.
987 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
988 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ||
989 (m_teleportFlags & TeleportFlags.ViaLocation) != 0)
990 {
991 // Don't restrict gods, estate managers, or land owners to
992 // the TP point. This behaviour mimics agni.
993 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
994 land.LandData.UserLocation != Vector3.Zero &&
995 GodLevel < 200 &&
996 ((land.LandData.OwnerID != m_uuid &&
997 (!m_scene.Permissions.IsGod(m_uuid)) &&
998 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0))
999 {
1000 pos = land.LandData.UserLocation;
1001 }
1002 }
1003
1004 land.SendLandUpdateToClient(ControllingClient);
1005 }
1006
1007 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
1008 {
1009 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
1010
1011 if (pos.X < 0)
1012 {
1013 emergencyPos.X = (int)Constants.RegionSize + pos.X;
1014 if (!(pos.Y < 0))
1015 emergencyPos.Y = pos.Y;
1016 if (!(pos.Z < 0))
1017 emergencyPos.Z = pos.Z;
1018 }
1019 if (pos.Y < 0)
1020 {
1021 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
1022 if (!(pos.X < 0))
1023 emergencyPos.X = pos.X;
1024 if (!(pos.Z < 0))
1025 emergencyPos.Z = pos.Z;
1026 }
1027 if (pos.Z < 0)
1028 {
1029 emergencyPos.Z = 128;
1030 if (!(pos.Y < 0))
1031 emergencyPos.Y = pos.Y;
1032 if (!(pos.X < 0))
1033 emergencyPos.X = pos.X;
1034 }
1035 }
1036
899 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1037 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
900 { 1038 {
901 m_log.WarnFormat( 1039 m_log.WarnFormat(
@@ -1028,16 +1166,21 @@ namespace OpenSim.Region.Framework.Scenes
1028 /// <summary> 1166 /// <summary>
1029 /// Removes physics plugin scene representation of this agent if it exists. 1167 /// Removes physics plugin scene representation of this agent if it exists.
1030 /// </summary> 1168 /// </summary>
1031 private void RemoveFromPhysicalScene() 1169 public void RemoveFromPhysicalScene()
1032 { 1170 {
1033 if (PhysicsActor != null) 1171 if (PhysicsActor != null)
1034 { 1172 {
1035 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1173 try
1036 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1174 {
1037 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1175 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1038 m_physicsActor.UnSubscribeEvents(); 1176 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
1039 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1177 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1040 PhysicsActor = null; 1178 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1179 m_physicsActor.UnSubscribeEvents();
1180 PhysicsActor = null;
1181 }
1182 catch
1183 { }
1041 } 1184 }
1042 } 1185 }
1043 1186
@@ -1048,15 +1191,18 @@ namespace OpenSim.Region.Framework.Scenes
1048 public void Teleport(Vector3 pos) 1191 public void Teleport(Vector3 pos)
1049 { 1192 {
1050 bool isFlying = false; 1193 bool isFlying = false;
1194
1051 if (m_physicsActor != null) 1195 if (m_physicsActor != null)
1052 isFlying = m_physicsActor.Flying; 1196 isFlying = m_physicsActor.Flying;
1053 1197
1054 RemoveFromPhysicalScene(); 1198 RemoveFromPhysicalScene();
1055 Velocity = Vector3.Zero; 1199 Velocity = Vector3.Zero;
1200 CheckLandingPoint(ref pos);
1056 AbsolutePosition = pos; 1201 AbsolutePosition = pos;
1057 AddToPhysicalScene(isFlying); 1202 AddToPhysicalScene(isFlying);
1058 1203
1059 SendTerseUpdateToAllClients(); 1204 SendTerseUpdateToAllClients();
1205
1060 } 1206 }
1061 1207
1062 public void TeleportWithMomentum(Vector3 pos) 1208 public void TeleportWithMomentum(Vector3 pos)
@@ -1066,6 +1212,7 @@ namespace OpenSim.Region.Framework.Scenes
1066 isFlying = m_physicsActor.Flying; 1212 isFlying = m_physicsActor.Flying;
1067 1213
1068 RemoveFromPhysicalScene(); 1214 RemoveFromPhysicalScene();
1215 CheckLandingPoint(ref pos);
1069 AbsolutePosition = pos; 1216 AbsolutePosition = pos;
1070 AddToPhysicalScene(isFlying); 1217 AddToPhysicalScene(isFlying);
1071 1218
@@ -1241,11 +1388,12 @@ namespace OpenSim.Region.Framework.Scenes
1241 /// <summary> 1388 /// <summary>
1242 /// This is the event handler for client movement. If a client is moving, this event is triggering. 1389 /// This is the event handler for client movement. If a client is moving, this event is triggering.
1243 /// </summary> 1390 /// </summary>
1391 /// <summary>
1392 /// This is the event handler for client movement. If a client is moving, this event is triggering.
1393 /// </summary>
1244 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 1394 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1245 { 1395 {
1246// m_log.DebugFormat( 1396 // m_log.DebugFormat("[SCENE PRESENCE]: Received agent update from {0}", remoteClient.Name);
1247// "[SCENE PRESENCE]: In {0} received agent update from {1}",
1248// Scene.RegionInfo.RegionName, remoteClient.Name);
1249 1397
1250 //if (m_isChildAgent) 1398 //if (m_isChildAgent)
1251 //{ 1399 //{
@@ -1441,12 +1589,12 @@ namespace OpenSim.Region.Framework.Scenes
1441 1589
1442 if ((m_movementflag & (byte)(uint)DCF) == 0) 1590 if ((m_movementflag & (byte)(uint)DCF) == 0)
1443 { 1591 {
1444 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) 1592 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACK_NUDGE)
1445 { 1593 {
1446 m_movementflag |= (byte)nudgehack; 1594 m_movementflag |= (byte)nudgehack;
1447 } 1595 }
1448 1596
1449// m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with {1}", Name, DCF); 1597 // m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with {1}", Name, DCF);
1450 m_movementflag += (byte)(uint)DCF; 1598 m_movementflag += (byte)(uint)DCF;
1451 update_movementflag = true; 1599 update_movementflag = true;
1452 } 1600 }
@@ -1454,11 +1602,11 @@ namespace OpenSim.Region.Framework.Scenes
1454 else 1602 else
1455 { 1603 {
1456 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1604 if ((m_movementflag & (byte)(uint)DCF) != 0 ||
1457 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) 1605 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACK_NUDGE)
1458 && ((m_movementflag & (byte)nudgehack) == nudgehack)) 1606 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1459 ) // This or is for Nudge forward 1607 ) // This or is for Nudge forward
1460 { 1608 {
1461// m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with lack of {1}", Name, DCF); 1609 // m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with lack of {1}", Name, DCF);
1462 m_movementflag -= ((byte)(uint)DCF); 1610 m_movementflag -= ((byte)(uint)DCF);
1463 update_movementflag = true; 1611 update_movementflag = true;
1464 1612
@@ -1523,21 +1671,21 @@ namespace OpenSim.Region.Framework.Scenes
1523 // which occurs later in the main scene loop 1671 // which occurs later in the main scene loop
1524 if (update_movementflag || (update_rotation && DCFlagKeyPressed)) 1672 if (update_movementflag || (update_rotation && DCFlagKeyPressed))
1525 { 1673 {
1526// m_log.DebugFormat( 1674 // m_log.DebugFormat(
1527// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", 1675 // "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}",
1528// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); 1676 // m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation);
1529 1677
1530 AddNewMovement(agent_control_v3); 1678 AddNewMovement(agent_control_v3);
1531 } 1679 }
1532// else 1680 // else
1533// { 1681 // {
1534// if (!update_movementflag) 1682 // if (!update_movementflag)
1535// { 1683 // {
1536// m_log.DebugFormat( 1684 // m_log.DebugFormat(
1537// "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false", 1685 // "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false",
1538// m_scene.RegionInfo.RegionName, agent_control_v3, Name); 1686 // m_scene.RegionInfo.RegionName, agent_control_v3, Name);
1539// } 1687 // }
1540// } 1688 // }
1541 1689
1542 if (update_movementflag && m_parentID == 0) 1690 if (update_movementflag && m_parentID == 0)
1543 Animator.UpdateMovementAnimations(); 1691 Animator.UpdateMovementAnimations();
@@ -1558,20 +1706,20 @@ namespace OpenSim.Region.Framework.Scenes
1558 /// <returns>True if movement has been updated in some way. False otherwise.</returns> 1706 /// <returns>True if movement has been updated in some way. False otherwise.</returns>
1559 public bool HandleMoveToTargetUpdate(ref Vector3 agent_control_v3) 1707 public bool HandleMoveToTargetUpdate(ref Vector3 agent_control_v3)
1560 { 1708 {
1561// m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name); 1709 // m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name);
1562 1710
1563 bool updated = false; 1711 bool updated = false;
1564 1712
1565// m_log.DebugFormat( 1713 // m_log.DebugFormat(
1566// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", 1714 // "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}",
1567// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); 1715 // allowUpdate, m_moveToPositionInProgress, m_autopilotMoving);
1568 1716
1569 if (!m_autopilotMoving) 1717 if (!m_autopilotMoving)
1570 { 1718 {
1571 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); 1719 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget);
1572// m_log.DebugFormat( 1720 // m_log.DebugFormat(
1573// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", 1721 // "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}",
1574// Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget); 1722 // Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget);
1575 1723
1576 // Check the error term of the current position in relation to the target position 1724 // Check the error term of the current position in relation to the target position
1577 if (distanceToTarget <= 1) 1725 if (distanceToTarget <= 1)
@@ -1594,7 +1742,7 @@ namespace OpenSim.Region.Framework.Scenes
1594 (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 1742 (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
1595 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords 1743 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords
1596 // Ignore z component of vector 1744 // Ignore z component of vector
1597// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1745 // Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1598 LocalVectorToTarget3D.Normalize(); 1746 LocalVectorToTarget3D.Normalize();
1599 1747
1600 // update avatar movement flags. the avatar coordinate system is as follows: 1748 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1660,9 +1808,9 @@ namespace OpenSim.Region.Framework.Scenes
1660 updated = true; 1808 updated = true;
1661 } 1809 }
1662 1810
1663// m_log.DebugFormat( 1811 // m_log.DebugFormat(
1664// "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}", 1812 // "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}",
1665// LocalVectorToTarget3D, agent_control_v3, Name); 1813 // LocalVectorToTarget3D, agent_control_v3, Name);
1666 1814
1667 agent_control_v3 += LocalVectorToTarget3D; 1815 agent_control_v3 += LocalVectorToTarget3D;
1668 } 1816 }
@@ -1783,7 +1931,7 @@ namespace OpenSim.Region.Framework.Scenes
1783 Velocity = Vector3.Zero; 1931 Velocity = Vector3.Zero;
1784 SendAvatarDataToAllAgents(); 1932 SendAvatarDataToAllAgents();
1785 1933
1786 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1934 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1787 } 1935 }
1788 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1936 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1789 m_requestedSitTargetUUID = UUID.Zero; 1937 m_requestedSitTargetUUID = UUID.Zero;
@@ -1820,25 +1968,22 @@ namespace OpenSim.Region.Framework.Scenes
1820 1968
1821 if (m_parentID != 0) 1969 if (m_parentID != 0)
1822 { 1970 {
1823 m_log.Debug("StandupCode Executed"); 1971 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1824 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1825 if (part != null) 1972 if (part != null)
1826 { 1973 {
1974 part.TaskInventory.LockItemsForRead(true);
1827 TaskInventoryDictionary taskIDict = part.TaskInventory; 1975 TaskInventoryDictionary taskIDict = part.TaskInventory;
1828 if (taskIDict != null) 1976 if (taskIDict != null)
1829 { 1977 {
1830 lock (taskIDict) 1978 foreach (UUID taskID in taskIDict.Keys)
1831 { 1979 {
1832 foreach (UUID taskID in taskIDict.Keys) 1980 UnRegisterControlEventsToScript(LocalId, taskID);
1833 { 1981 taskIDict[taskID].PermsMask &= ~(
1834 UnRegisterControlEventsToScript(LocalId, taskID); 1982 2048 | //PERMISSION_CONTROL_CAMERA
1835 taskIDict[taskID].PermsMask &= ~( 1983 4); // PERMISSION_TAKE_CONTROLS
1836 2048 | //PERMISSION_CONTROL_CAMERA
1837 4); // PERMISSION_TAKE_CONTROLS
1838 }
1839 } 1984 }
1840
1841 } 1985 }
1986 part.TaskInventory.LockItemsForRead(false);
1842 // Reset sit target. 1987 // Reset sit target.
1843 if (part.GetAvatarOnSitTarget() == UUID) 1988 if (part.GetAvatarOnSitTarget() == UUID)
1844 part.SitTargetAvatar = UUID.Zero; 1989 part.SitTargetAvatar = UUID.Zero;
@@ -1847,20 +1992,58 @@ namespace OpenSim.Region.Framework.Scenes
1847 m_parentPosition = part.GetWorldPosition(); 1992 m_parentPosition = part.GetWorldPosition();
1848 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1993 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1849 } 1994 }
1995 // part.GetWorldRotation() is the rotation of the object being sat on
1996 // Rotation is the sittiing Av's rotation
1997
1998 Quaternion partRot;
1999// if (part.LinkNum == 1)
2000// { // Root prim of linkset
2001// partRot = part.ParentGroup.RootPart.RotationOffset;
2002// }
2003// else
2004// { // single or child prim
2005
2006// }
2007 if (part == null) //CW: Part may be gone. llDie() for example.
2008 {
2009 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
2010 }
2011 else
2012 {
2013 partRot = part.GetWorldRotation();
2014 }
2015
2016 Quaternion partIRot = Quaternion.Inverse(partRot);
1850 2017
2018 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
2019 Vector3 avStandUp = new Vector3(0.3f, 0f, 0f) * avatarRot; // 0.3M infront of av
2020
2021
1851 if (m_physicsActor == null) 2022 if (m_physicsActor == null)
1852 { 2023 {
1853 AddToPhysicalScene(false); 2024 AddToPhysicalScene(false);
1854 } 2025 }
1855 2026 //CW: If the part isn't null then we can set the current position
1856 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 2027 if (part != null)
1857 m_parentPosition = Vector3.Zero; 2028 {
1858 2029 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1859 m_parentID = 0; 2030 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
2031 part.IsOccupied = false;
2032 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
2033 }
2034 else
2035 {
2036 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
2037 AbsolutePosition = m_lastWorldPosition;
2038 }
2039
2040 m_parentPosition = Vector3.Zero;
2041 m_parentID = 0;
2042 m_linkedPrim = UUID.Zero;
2043 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1860 SendAvatarDataToAllAgents(); 2044 SendAvatarDataToAllAgents();
1861 m_requestedSitTargetID = 0; 2045 m_requestedSitTargetID = 0;
1862 } 2046 }
1863
1864 Animator.TrySetMovementAnimation("STAND"); 2047 Animator.TrySetMovementAnimation("STAND");
1865 } 2048 }
1866 2049
@@ -1891,13 +2074,9 @@ namespace OpenSim.Region.Framework.Scenes
1891 Vector3 avSitOffSet = part.SitTargetPosition; 2074 Vector3 avSitOffSet = part.SitTargetPosition;
1892 Quaternion avSitOrientation = part.SitTargetOrientation; 2075 Quaternion avSitOrientation = part.SitTargetOrientation;
1893 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2076 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1894 2077 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1895 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2078 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1896 bool SitTargetisSet = 2079 if (SitTargetisSet && !SitTargetOccupied)
1897 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1898 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1899
1900 if (SitTargetisSet && SitTargetUnOccupied)
1901 { 2080 {
1902 //switch the target to this prim 2081 //switch the target to this prim
1903 return part; 2082 return part;
@@ -1911,85 +2090,168 @@ namespace OpenSim.Region.Framework.Scenes
1911 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 2090 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1912 { 2091 {
1913 bool autopilot = true; 2092 bool autopilot = true;
2093 Vector3 autopilotTarget = new Vector3();
2094 Quaternion sitOrientation = Quaternion.Identity;
1914 Vector3 pos = new Vector3(); 2095 Vector3 pos = new Vector3();
1915 Quaternion sitOrientation = pSitOrientation;
1916 Vector3 cameraEyeOffset = Vector3.Zero; 2096 Vector3 cameraEyeOffset = Vector3.Zero;
1917 Vector3 cameraAtOffset = Vector3.Zero; 2097 Vector3 cameraAtOffset = Vector3.Zero;
1918 bool forceMouselook = false; 2098 bool forceMouselook = false;
1919 2099
1920 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 2100 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1921 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 2101 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1922 if (part != null) 2102 if (part == null) return;
2103
2104 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
2105 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
2106
2107 // part is the prim to sit on
2108 // offset is the world-ref vector distance from that prim center to the click-spot
2109 // UUID is the UUID of the Avatar doing the clicking
2110
2111 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
2112
2113 // Is a sit target available?
2114 Vector3 avSitOffSet = part.SitTargetPosition;
2115 Quaternion avSitOrientation = part.SitTargetOrientation;
2116
2117 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
2118 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
2119 Quaternion partRot;
2120// if (part.LinkNum == 1)
2121// { // Root prim of linkset
2122// partRot = part.ParentGroup.RootPart.RotationOffset;
2123// }
2124// else
2125// { // single or child prim
2126 partRot = part.GetWorldRotation();
2127// }
2128 Quaternion partIRot = Quaternion.Inverse(partRot);
2129//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
2130 // Sit analysis rewritten by KF 091125
2131 if (SitTargetisSet) // scipted sit
1923 { 2132 {
1924 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 2133 if (!part.IsOccupied)
1925 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 2134 {
1926 2135//Console.WriteLine("Scripted, unoccupied");
1927 // Is a sit target available? 2136 part.SitTargetAvatar = UUID; // set that Av will be on it
1928 Vector3 avSitOffSet = part.SitTargetPosition; 2137 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1929 Quaternion avSitOrientation = part.SitTargetOrientation; 2138
1930 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2139 Quaternion nrot = avSitOrientation;
1931 2140 if (!part.IsRoot)
1932 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
1933 bool SitTargetisSet =
1934 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f &&
1935 (
1936 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion
1937 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point
1938 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion
1939 )
1940 ));
1941
1942 if (SitTargetisSet && SitTargetUnOccupied)
1943 {
1944 part.SitTargetAvatar = UUID;
1945 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z);
1946 sitOrientation = avSitOrientation;
1947 autopilot = false;
1948 }
1949 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1950
1951 pos = part.AbsolutePosition + offset;
1952 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1)
1953 //{
1954 // offset = pos;
1955 //autopilot = false;
1956 //}
1957 if (m_physicsActor != null)
1958 {
1959 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1960 // We can remove the physicsActor until they stand up.
1961 m_sitAvatarHeight = m_physicsActor.Size.Z;
1962
1963 if (autopilot)
1964 { 2141 {
1965 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 2142 nrot = part.RotationOffset * avSitOrientation;
1966 {
1967 autopilot = false;
1968
1969 RemoveFromPhysicalScene();
1970 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1971 }
1972 } 2143 }
1973 else 2144 sitOrientation = nrot; // Change rotatione to the scripted one
2145 OffsetRotation = nrot;
2146 autopilot = false; // Jump direct to scripted llSitPos()
2147 }
2148 else
2149 {
2150//Console.WriteLine("Scripted, occupied");
2151 return;
2152 }
2153 }
2154 else // Not Scripted
2155 {
2156 if ( (Math.Abs(offset.X) > 0.1f) || (Math.Abs(offset.Y) > 0.1f) ) // Changed 0.5M to 0.1M as they want to be able to sit close together
2157 {
2158 // large prim & offset, ignore if other Avs sitting
2159// offset.Z -= 0.05f;
2160 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
2161 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
2162
2163//Console.WriteLine(" offset ={0}", offset);
2164//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
2165//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
2166
2167 }
2168 else // small offset
2169 {
2170//Console.WriteLine("Small offset");
2171 if (!part.IsOccupied)
2172 {
2173 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2174 autopilotTarget = part.AbsolutePosition;
2175//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2176 }
2177 else return; // occupied small
2178 } // end large/small
2179 } // end Scripted/not
2180
2181 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2182
2183 cameraAtOffset = part.GetCameraAtOffset();
2184 cameraEyeOffset = part.GetCameraEyeOffset();
2185 forceMouselook = part.GetForceMouselook();
2186 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2187 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2188
2189 if (m_physicsActor != null)
2190 {
2191 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2192 // We can remove the physicsActor until they stand up.
2193 m_sitAvatarHeight = m_physicsActor.Size.Z;
2194 if (autopilot)
2195 { // its not a scripted sit
2196// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2197 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1974 { 2198 {
2199 autopilot = false; // close enough
2200 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2201 Not using the part's position because returning the AV to the last known standing
2202 position is likely to be more friendly, isn't it? */
1975 RemoveFromPhysicalScene(); 2203 RemoveFromPhysicalScene();
1976 } 2204 Velocity = Vector3.Zero;
2205 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2206 } // else the autopilot will get us close
2207 }
2208 else
2209 { // its a scripted sit
2210 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2211 I *am* using the part's position this time because we have no real idea how far away
2212 the avatar is from the sit target. */
2213 RemoveFromPhysicalScene();
2214 Velocity = Vector3.Zero;
1977 } 2215 }
1978
1979 cameraAtOffset = part.GetCameraAtOffset();
1980 cameraEyeOffset = part.GetCameraEyeOffset();
1981 forceMouselook = part.GetForceMouselook();
1982 } 2216 }
1983 2217 else return; // physactor is null!
1984 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2218
1985 m_requestedSitTargetUUID = targetID; 2219 Vector3 offsetr; // = offset * partIRot;
2220 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2221 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2222 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2223 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2224 //offsetr = offset * partIRot;
2225//
2226 // }
2227 // else
2228 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2229 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2230 // (offset * partRot);
2231 // }
2232
2233//Console.WriteLine(" ");
2234//Console.WriteLine("link number ={0}", part.LinkNum);
2235//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2236//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2237//Console.WriteLine("Click offst ={0}", offset);
2238//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2239//Console.WriteLine("offsetr ={0}", offsetr);
2240//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2241//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2242
2243 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2244 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2245
2246 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1986 // This calls HandleAgentSit twice, once from here, and the client calls 2247 // This calls HandleAgentSit twice, once from here, and the client calls
1987 // HandleAgentSit itself after it gets to the location 2248 // HandleAgentSit itself after it gets to the location
1988 // It doesn't get to the location until we've moved them there though 2249 // It doesn't get to the location until we've moved them there though
1989 // which happens in HandleAgentSit :P 2250 // which happens in HandleAgentSit :P
1990 m_autopilotMoving = autopilot; 2251 m_autopilotMoving = autopilot;
1991 m_autoPilotTarget = pos; 2252 m_autoPilotTarget = autopilotTarget;
1992 m_sitAtAutoTarget = autopilot; 2253 m_sitAtAutoTarget = autopilot;
2254 m_initialSitTarget = autopilotTarget;
1993 if (!autopilot) 2255 if (!autopilot)
1994 HandleAgentSit(remoteClient, UUID); 2256 HandleAgentSit(remoteClient, UUID);
1995 } 2257 }
@@ -2254,47 +2516,130 @@ namespace OpenSim.Region.Framework.Scenes
2254 { 2516 {
2255 if (part != null) 2517 if (part != null)
2256 { 2518 {
2519//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2257 if (part.GetAvatarOnSitTarget() == UUID) 2520 if (part.GetAvatarOnSitTarget() == UUID)
2258 { 2521 {
2522//Console.WriteLine("Scripted Sit");
2523 // Scripted sit
2259 Vector3 sitTargetPos = part.SitTargetPosition; 2524 Vector3 sitTargetPos = part.SitTargetPosition;
2260 Quaternion sitTargetOrient = part.SitTargetOrientation; 2525 Quaternion sitTargetOrient = part.SitTargetOrientation;
2261
2262 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2263 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2264
2265 //Quaternion result = (sitTargetOrient * vq) * nq;
2266
2267 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2526 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2268 m_pos += SIT_TARGET_ADJUSTMENT; 2527 m_pos += SIT_TARGET_ADJUSTMENT;
2528 if (!part.IsRoot)
2529 {
2530 m_pos *= part.RotationOffset;
2531 }
2269 m_bodyRot = sitTargetOrient; 2532 m_bodyRot = sitTargetOrient;
2270 //Rotation = sitTargetOrient;
2271 m_parentPosition = part.AbsolutePosition; 2533 m_parentPosition = part.AbsolutePosition;
2272 2534 part.IsOccupied = true;
2273 //SendTerseUpdateToAllClients(); 2535 part.ParentGroup.AddAvatar(agentID);
2274 } 2536 }
2275 else 2537 else
2276 { 2538 {
2277 m_pos -= part.AbsolutePosition; 2539 // if m_avUnscriptedSitPos is zero then Av sits above center
2540 // Else Av sits at m_avUnscriptedSitPos
2541
2542 // Non-scripted sit by Kitto Flora 21Nov09
2543 // Calculate angle of line from prim to Av
2544 Quaternion partIRot;
2545// if (part.LinkNum == 1)
2546// { // Root prim of linkset
2547// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2548// }
2549// else
2550// { // single or child prim
2551 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2552// }
2553 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2554 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2555 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2556 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2557 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2558 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2559 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2560 // Av sits at world euler <0,0, z>, translated by part rotation
2561 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2562
2278 m_parentPosition = part.AbsolutePosition; 2563 m_parentPosition = part.AbsolutePosition;
2279 } 2564 part.IsOccupied = true;
2565 part.ParentGroup.AddAvatar(agentID);
2566 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2567 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2568 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2569 m_avUnscriptedSitPos; // adds click offset, if any
2570 //Set up raytrace to find top surface of prim
2571 Vector3 size = part.Scale;
2572 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2573 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2574 Vector3 down = new Vector3(0f, 0f, -1f);
2575//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2576 m_scene.PhysicsScene.RaycastWorld(
2577 start, // Vector3 position,
2578 down, // Vector3 direction,
2579 mag, // float length,
2580 SitAltitudeCallback); // retMethod
2581 } // end scripted/not
2280 } 2582 }
2281 else 2583 else // no Av
2282 { 2584 {
2283 return; 2585 return;
2284 } 2586 }
2285 } 2587 }
2286 m_parentID = m_requestedSitTargetID;
2287 2588
2589 //We want our offsets to reference the root prim, not the child we may have sat on
2590 if (!part.IsRoot)
2591 {
2592 m_parentID = part.ParentGroup.RootPart.LocalId;
2593 m_pos += part.OffsetPosition;
2594 }
2595 else
2596 {
2597 m_parentID = m_requestedSitTargetID;
2598 }
2599
2600 m_linkedPrim = part.UUID;
2601 if (part.GetAvatarOnSitTarget() != UUID)
2602 {
2603 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2604 }
2288 Velocity = Vector3.Zero; 2605 Velocity = Vector3.Zero;
2289 RemoveFromPhysicalScene(); 2606 RemoveFromPhysicalScene();
2290
2291 Animator.TrySetMovementAnimation(sitAnimation); 2607 Animator.TrySetMovementAnimation(sitAnimation);
2292 SendAvatarDataToAllAgents(); 2608 SendAvatarDataToAllAgents();
2293 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2294 // So we're also sending a terse update (which has avatar rotation)
2295 // [Update] We do now.
2296 //SendTerseUpdateToAllClients(); 2609 //SendTerseUpdateToAllClients();
2297 } 2610 }
2611
2612 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2613 {
2614 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2615 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2616 if(hitYN)
2617 {
2618 // m_pos = Av offset from prim center to make look like on center
2619 // m_parentPosition = Actual center pos of prim
2620 // collisionPoint = spot on prim where we want to sit
2621 // collisionPoint.Z = global sit surface height
2622 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2623 Quaternion partIRot;
2624// if (part.LinkNum == 1)
2625/// { // Root prim of linkset
2626// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2627// }
2628// else
2629// { // single or child prim
2630 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2631// }
2632 if (m_initialSitTarget != null)
2633 {
2634 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2635 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2636 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2637 m_pos += offset;
2638 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2639 }
2640
2641 }
2642 } // End SitAltitudeCallback KF.
2298 2643
2299 /// <summary> 2644 /// <summary>
2300 /// Event handler for the 'Always run' setting on the client 2645 /// Event handler for the 'Always run' setting on the client
@@ -2414,6 +2759,9 @@ namespace OpenSim.Region.Framework.Scenes
2414 2759
2415 CheckForSignificantMovement(); // sends update to the modules. 2760 CheckForSignificantMovement(); // sends update to the modules.
2416 } 2761 }
2762
2763 //Sending prim updates AFTER the avatar terse updates are sent
2764 SendPrimUpdates();
2417 } 2765 }
2418 2766
2419 #endregion 2767 #endregion
@@ -3227,6 +3575,7 @@ namespace OpenSim.Region.Framework.Scenes
3227 m_callbackURI = cAgent.CallbackURI; 3575 m_callbackURI = cAgent.CallbackURI;
3228 3576
3229 m_pos = cAgent.Position; 3577 m_pos = cAgent.Position;
3578
3230 m_velocity = cAgent.Velocity; 3579 m_velocity = cAgent.Velocity;
3231 m_CameraCenter = cAgent.Center; 3580 m_CameraCenter = cAgent.Center;
3232 m_CameraAtAxis = cAgent.AtAxis; 3581 m_CameraAtAxis = cAgent.AtAxis;
@@ -3343,10 +3692,8 @@ namespace OpenSim.Region.Framework.Scenes
3343 3692
3344 Vector3 pVec = AbsolutePosition; 3693 Vector3 pVec = AbsolutePosition;
3345 3694
3346 // Old bug where the height was in centimeters instead of meters 3695 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3347 m_physicsActor = scene.AddAvatar(LocalId, Firstname + "." + Lastname, pVec,
3348 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3696 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3349
3350 scene.AddPhysicsActorTaint(m_physicsActor); 3697 scene.AddPhysicsActorTaint(m_physicsActor);
3351 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3698 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3352 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3699 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3372,18 +3719,29 @@ namespace OpenSim.Region.Framework.Scenes
3372 { 3719 {
3373 if (e == null) 3720 if (e == null)
3374 return; 3721 return;
3375 3722
3376 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3723 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3377 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3378 // as of this comment the interval is set in AddToPhysicalScene 3724 // as of this comment the interval is set in AddToPhysicalScene
3379 if (Animator != null) 3725 if (Animator!=null)
3380 Animator.UpdateMovementAnimations(); 3726 {
3727 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3728 { // else its will lock out other animation changes, like ground sit.
3729 Animator.UpdateMovementAnimations();
3730 m_updateCount--;
3731 }
3732 }
3381 3733
3382 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3734 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3383 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3735 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3384 3736
3385 CollisionPlane = Vector4.UnitW; 3737 CollisionPlane = Vector4.UnitW;
3386 3738
3739 if (m_lastColCount != coldata.Count)
3740 {
3741 m_updateCount = UPDATE_COUNT;
3742 m_lastColCount = coldata.Count;
3743 }
3744
3387 if (coldata.Count != 0 && Animator != null) 3745 if (coldata.Count != 0 && Animator != null)
3388 { 3746 {
3389 switch (Animator.CurrentMovementAnimation) 3747 switch (Animator.CurrentMovementAnimation)
@@ -3413,6 +3771,148 @@ namespace OpenSim.Region.Framework.Scenes
3413 } 3771 }
3414 } 3772 }
3415 3773
3774 List<uint> thisHitColliders = new List<uint>();
3775 List<uint> endedColliders = new List<uint>();
3776 List<uint> startedColliders = new List<uint>();
3777
3778 foreach (uint localid in coldata.Keys)
3779 {
3780 thisHitColliders.Add(localid);
3781 if (!m_lastColliders.Contains(localid))
3782 {
3783 startedColliders.Add(localid);
3784 }
3785 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3786 }
3787
3788 // calculate things that ended colliding
3789 foreach (uint localID in m_lastColliders)
3790 {
3791 if (!thisHitColliders.Contains(localID))
3792 {
3793 endedColliders.Add(localID);
3794 }
3795 }
3796 //add the items that started colliding this time to the last colliders list.
3797 foreach (uint localID in startedColliders)
3798 {
3799 m_lastColliders.Add(localID);
3800 }
3801 // remove things that ended colliding from the last colliders list
3802 foreach (uint localID in endedColliders)
3803 {
3804 m_lastColliders.Remove(localID);
3805 }
3806
3807 // do event notification
3808 if (startedColliders.Count > 0)
3809 {
3810 ColliderArgs StartCollidingMessage = new ColliderArgs();
3811 List<DetectedObject> colliding = new List<DetectedObject>();
3812 foreach (uint localId in startedColliders)
3813 {
3814 if (localId == 0)
3815 continue;
3816
3817 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3818 string data = "";
3819 if (obj != null)
3820 {
3821 DetectedObject detobj = new DetectedObject();
3822 detobj.keyUUID = obj.UUID;
3823 detobj.nameStr = obj.Name;
3824 detobj.ownerUUID = obj.OwnerID;
3825 detobj.posVector = obj.AbsolutePosition;
3826 detobj.rotQuat = obj.GetWorldRotation();
3827 detobj.velVector = obj.Velocity;
3828 detobj.colliderType = 0;
3829 detobj.groupUUID = obj.GroupID;
3830 colliding.Add(detobj);
3831 }
3832 }
3833
3834 if (colliding.Count > 0)
3835 {
3836 StartCollidingMessage.Colliders = colliding;
3837
3838 foreach (SceneObjectGroup att in GetAttachments())
3839 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3840 }
3841 }
3842
3843 if (endedColliders.Count > 0)
3844 {
3845 ColliderArgs EndCollidingMessage = new ColliderArgs();
3846 List<DetectedObject> colliding = new List<DetectedObject>();
3847 foreach (uint localId in endedColliders)
3848 {
3849 if (localId == 0)
3850 continue;
3851
3852 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3853 string data = "";
3854 if (obj != null)
3855 {
3856 DetectedObject detobj = new DetectedObject();
3857 detobj.keyUUID = obj.UUID;
3858 detobj.nameStr = obj.Name;
3859 detobj.ownerUUID = obj.OwnerID;
3860 detobj.posVector = obj.AbsolutePosition;
3861 detobj.rotQuat = obj.GetWorldRotation();
3862 detobj.velVector = obj.Velocity;
3863 detobj.colliderType = 0;
3864 detobj.groupUUID = obj.GroupID;
3865 colliding.Add(detobj);
3866 }
3867 }
3868
3869 if (colliding.Count > 0)
3870 {
3871 EndCollidingMessage.Colliders = colliding;
3872
3873 foreach (SceneObjectGroup att in GetAttachments())
3874 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3875 }
3876 }
3877
3878 if (thisHitColliders.Count > 0)
3879 {
3880 ColliderArgs CollidingMessage = new ColliderArgs();
3881 List<DetectedObject> colliding = new List<DetectedObject>();
3882 foreach (uint localId in thisHitColliders)
3883 {
3884 if (localId == 0)
3885 continue;
3886
3887 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3888 string data = "";
3889 if (obj != null)
3890 {
3891 DetectedObject detobj = new DetectedObject();
3892 detobj.keyUUID = obj.UUID;
3893 detobj.nameStr = obj.Name;
3894 detobj.ownerUUID = obj.OwnerID;
3895 detobj.posVector = obj.AbsolutePosition;
3896 detobj.rotQuat = obj.GetWorldRotation();
3897 detobj.velVector = obj.Velocity;
3898 detobj.colliderType = 0;
3899 detobj.groupUUID = obj.GroupID;
3900 colliding.Add(detobj);
3901 }
3902 }
3903
3904 if (colliding.Count > 0)
3905 {
3906 CollidingMessage.Colliders = colliding;
3907
3908 lock (m_attachments)
3909 {
3910 foreach (SceneObjectGroup att in m_attachments)
3911 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3912 }
3913 }
3914 }
3915
3416 if (m_invulnerable) 3916 if (m_invulnerable)
3417 return; 3917 return;
3418 3918
@@ -3486,6 +3986,10 @@ namespace OpenSim.Region.Framework.Scenes
3486 { 3986 {
3487 lock (m_attachments) 3987 lock (m_attachments)
3488 { 3988 {
3989 // This may be true when the attachment comes back
3990 // from serialization after login. Clear it.
3991 gobj.IsDeleted = false;
3992
3489 m_attachments.Add(gobj); 3993 m_attachments.Add(gobj);
3490 } 3994 }
3491 } 3995 }
@@ -3849,5 +4353,39 @@ namespace OpenSim.Region.Framework.Scenes
3849 m_reprioritization_called = false; 4353 m_reprioritization_called = false;
3850 } 4354 }
3851 } 4355 }
4356
4357 private Vector3 Quat2Euler(Quaternion rot){
4358 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4359 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4360 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4361 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4362 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4363 return(new Vector3(x,y,z));
4364 }
4365
4366 private void CheckLandingPoint(ref Vector3 pos)
4367 {
4368 // Never constrain lures
4369 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
4370 return;
4371
4372 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
4373 return;
4374
4375 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
4376
4377 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
4378 land.LandData.UserLocation != Vector3.Zero &&
4379 land.LandData.OwnerID != m_uuid &&
4380 (!m_scene.Permissions.IsGod(m_uuid)) &&
4381 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)))
4382 {
4383 float curr = Vector3.Distance(AbsolutePosition, pos);
4384 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
4385 pos = land.LandData.UserLocation;
4386 else
4387 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
4388 }
4389 }
3852 } 4390 }
3853} 4391}
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
index 50e1e39..8a0d288 100644
--- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
@@ -126,7 +126,7 @@ namespace OpenSim.Region.Framework.Scenes
126 g.ScheduleFullUpdateToAvatar(m_presence); 126 g.ScheduleFullUpdateToAvatar(m_presence);
127 } 127 }
128 128
129 while (m_partsUpdateQueue.Count > 0) 129 while (m_partsUpdateQueue != null && m_partsUpdateQueue.Count != null && m_partsUpdateQueue.Count > 0)
130 { 130 {
131 SceneObjectPart part = m_partsUpdateQueue.Dequeue(); 131 SceneObjectPart part = m_partsUpdateQueue.Dequeue();
132 132
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index e06a222..11dad6c 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -346,6 +346,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
346 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 346 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
347 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 347 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
348 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 348 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
349
350 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
349 #endregion 351 #endregion
350 352
351 #region TaskInventoryXmlProcessors initialization 353 #region TaskInventoryXmlProcessors initialization
@@ -735,6 +737,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
735 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 737 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
736 } 738 }
737 739
740 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
741 {
742 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
743 }
744
738 #endregion 745 #endregion
739 746
740 #region TaskInventoryXmlProcessors 747 #region TaskInventoryXmlProcessors
@@ -1219,6 +1226,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1219 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1226 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1220 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1227 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1221 1228
1229 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1230
1222 writer.WriteEndElement(); 1231 writer.WriteEndElement();
1223 } 1232 }
1224 1233
@@ -1503,12 +1512,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1503 { 1512 {
1504 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1513 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1505 1514
1506 if (reader.IsEmptyElement)
1507 {
1508 reader.Read();
1509 return tinv;
1510 }
1511
1512 reader.ReadStartElement(name, String.Empty); 1515 reader.ReadStartElement(name, String.Empty);
1513 1516
1514 while (reader.Name == "TaskInventoryItem") 1517 while (reader.Name == "TaskInventoryItem")
@@ -1551,12 +1554,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1551 1554
1552 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1555 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1553 1556
1554 if (reader.IsEmptyElement)
1555 {
1556 reader.Read();
1557 return shape;
1558 }
1559
1560 reader.ReadStartElement(name, String.Empty); // Shape 1557 reader.ReadStartElement(name, String.Empty); // Shape
1561 1558
1562 string nodeName = string.Empty; 1559 string nodeName = string.Empty;
@@ -1596,4 +1593,4 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1596 1593
1597 #endregion 1594 #endregion
1598 } 1595 }
1599} 1596} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index d34d8e5..0a30f4b 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -30,12 +30,27 @@ using System.Reflection;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
33using System;
33 34
34namespace OpenSim.Region.Framework.Scenes 35namespace OpenSim.Region.Framework.Scenes
35{ 36{
37 [Flags]
38 public enum UndoType
39 {
40 STATE_PRIM_POSITION = 1,
41 STATE_PRIM_ROTATION = 2,
42 STATE_PRIM_SCALE = 4,
43 STATE_PRIM_ALL = 7,
44 STATE_GROUP_POSITION = 8,
45 STATE_GROUP_ROTATION = 16,
46 STATE_GROUP_SCALE = 32,
47 STATE_GROUP_ALL = 56,
48 STATE_ALL = 63
49 }
50
36 public class UndoState 51 public class UndoState
37 { 52 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53 // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
39 54
40 public Vector3 Position = Vector3.Zero; 55 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero; 56 public Vector3 Scale = Vector3.Zero;
@@ -57,37 +72,37 @@ namespace OpenSim.Region.Framework.Scenes
57 { 72 {
58 ForGroup = forGroup; 73 ForGroup = forGroup;
59 74
60// if (ForGroup) 75 // if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition; 76 Position = part.ParentGroup.AbsolutePosition;
62// else 77 // else
63// Position = part.OffsetPosition; 78 // Position = part.OffsetPosition;
64 79
65// m_log.DebugFormat( 80 // m_log.DebugFormat(
66// "[UNDO STATE]: Storing undo position {0} for root part", Position); 81 // "[UNDO STATE]: Storing undo position {0} for root part", Position);
67 82
68 Rotation = part.RotationOffset; 83 Rotation = part.RotationOffset;
69 84
70// m_log.DebugFormat( 85 // m_log.DebugFormat(
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); 86 // "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation);
72 87
73 Scale = part.Shape.Scale; 88 Scale = part.Shape.Scale;
74 89
75// m_log.DebugFormat( 90 // m_log.DebugFormat(
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale); 91 // "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 92 }
78 else 93 else
79 { 94 {
80 Position = part.OffsetPosition; 95 Position = part.OffsetPosition;
81// m_log.DebugFormat( 96 // m_log.DebugFormat(
82// "[UNDO STATE]: Storing undo position {0} for child part", Position); 97 // "[UNDO STATE]: Storing undo position {0} for child part", Position);
83 98
84 Rotation = part.RotationOffset; 99 Rotation = part.RotationOffset;
85// m_log.DebugFormat( 100 // m_log.DebugFormat(
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); 101 // "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation);
87 102
88 Scale = part.Shape.Scale; 103 Scale = part.Shape.Scale;
89// m_log.DebugFormat( 104 // m_log.DebugFormat(
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 105 // "[UNDO STATE]: Storing undo scale {0} for child part", Scale);
91 } 106 }
92 } 107 }
93 108
@@ -121,9 +136,9 @@ namespace OpenSim.Region.Framework.Scenes
121 136
122 if (part.ParentID == 0) 137 if (part.ParentID == 0)
123 { 138 {
124// m_log.DebugFormat( 139 // m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}", 140 // "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId); 141 // Position, part.Name, part.LocalId);
127 142
128 if (Position != Vector3.Zero) 143 if (Position != Vector3.Zero)
129 { 144 {
@@ -133,9 +148,9 @@ namespace OpenSim.Region.Framework.Scenes
133 part.ParentGroup.UpdateRootPosition(Position); 148 part.ParentGroup.UpdateRootPosition(Position);
134 } 149 }
135 150
136// m_log.DebugFormat( 151 // m_log.DebugFormat(
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", 152 // "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}",
138// part.RotationOffset, Rotation, part.Name, part.LocalId); 153 // part.RotationOffset, Rotation, part.Name, part.LocalId);
139 154
140 if (ForGroup) 155 if (ForGroup)
141 part.UpdateRotation(Rotation); 156 part.UpdateRotation(Rotation);
@@ -144,9 +159,9 @@ namespace OpenSim.Region.Framework.Scenes
144 159
145 if (Scale != Vector3.Zero) 160 if (Scale != Vector3.Zero)
146 { 161 {
147// m_log.DebugFormat( 162 // m_log.DebugFormat(
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", 163 // "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}",
149// part.Shape.Scale, Scale, part.Name, part.LocalId); 164 // part.Shape.Scale, Scale, part.Name, part.LocalId);
150 165
151 if (ForGroup) 166 if (ForGroup)
152 part.ParentGroup.GroupResize(Scale); 167 part.ParentGroup.GroupResize(Scale);
@@ -160,24 +175,24 @@ namespace OpenSim.Region.Framework.Scenes
160 { 175 {
161 if (Position != Vector3.Zero) 176 if (Position != Vector3.Zero)
162 { 177 {
163// m_log.DebugFormat( 178 // m_log.DebugFormat(
164// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}", 179 // "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
165// part.OffsetPosition, Position, part.Name, part.LocalId); 180 // part.OffsetPosition, Position, part.Name, part.LocalId);
166 181
167 part.OffsetPosition = Position; 182 part.OffsetPosition = Position;
168 } 183 }
169 184
170// m_log.DebugFormat( 185 // m_log.DebugFormat(
171// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", 186 // "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}",
172// part.RotationOffset, Rotation, part.Name, part.LocalId); 187 // part.RotationOffset, Rotation, part.Name, part.LocalId);
173 188
174 part.UpdateRotation(Rotation); 189 part.UpdateRotation(Rotation);
175 190
176 if (Scale != Vector3.Zero) 191 if (Scale != Vector3.Zero)
177 { 192 {
178// m_log.DebugFormat( 193 // m_log.DebugFormat(
179// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", 194 // "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}",
180// part.Shape.Scale, Scale, part.Name, part.LocalId); 195 // part.Shape.Scale, Scale, part.Name, part.LocalId);
181 196
182 part.Resize(Scale); 197 part.Resize(Scale);
183 } 198 }
@@ -249,4 +264,4 @@ namespace OpenSim.Region.Framework.Scenes
249 m_terrainModule.UndoTerrain(m_terrainChannel); 264 m_terrainModule.UndoTerrain(m_terrainChannel);
250 } 265 }
251 } 266 }
252} \ No newline at end of file 267}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 3acdaf8..8d41f00 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -87,10 +87,6 @@ namespace OpenSim.Region.Framework.Scenes
87 /// <param name="assetUuids">The assets gathered</param> 87 /// <param name="assetUuids">The assets gathered</param>
88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
89 { 89 {
90 // avoid infinite loops
91 if (assetUuids.ContainsKey(assetUuid))
92 return;
93
94 try 90 try
95 { 91 {
96 assetUuids[assetUuid] = assetType; 92 assetUuids[assetUuid] = assetType;