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.cs452
-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.cs238
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs758
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs919
-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, 2950 insertions, 1011 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 9dcd10a..c2ec5d0 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.GetProperties(remoteClient); 264 part.GetProperties(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;
@@ -347,6 +329,7 @@ namespace OpenSim.Region.Framework.Scenes
347 { 329 {
348 if (UUID.Zero == transactionID) 330 if (UUID.Zero == transactionID)
349 { 331 {
332 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
350 item.Name = itemUpd.Name; 333 item.Name = itemUpd.Name;
351 item.Description = itemUpd.Description; 334 item.Description = itemUpd.Description;
352 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 335 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -725,6 +708,8 @@ namespace OpenSim.Region.Framework.Scenes
725 return; 708 return;
726 } 709 }
727 710
711 if (newName == null) newName = item.Name;
712
728 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 713 AssetBase asset = AssetService.Get(item.AssetID.ToString());
729 714
730 if (asset != null) 715 if (asset != null)
@@ -781,6 +766,24 @@ namespace OpenSim.Region.Framework.Scenes
781 } 766 }
782 767
783 /// <summary> 768 /// <summary>
769 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
770 /// </summary>
771 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
772 {
773 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
774 foreach (InventoryItemBase b in items)
775 {
776 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
777 InventoryItemBase n = InventoryService.GetItem(b);
778 n.Folder = destfolder;
779 moveitems.Add(n);
780 remoteClient.SendInventoryItemCreateUpdate(n, 0);
781 }
782
783 MoveInventoryItem(remoteClient, moveitems);
784 }
785
786 /// <summary>
784 /// Move an item within the agent's inventory. 787 /// Move an item within the agent's inventory.
785 /// </summary> 788 /// </summary>
786 /// <param name="remoteClient"></param> 789 /// <param name="remoteClient"></param>
@@ -981,25 +984,29 @@ namespace OpenSim.Region.Framework.Scenes
981 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 984 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
982 { 985 {
983 SceneObjectPart part = GetSceneObjectPart(localID); 986 SceneObjectPart part = GetSceneObjectPart(localID);
984 if (part == null) 987 SceneObjectGroup group = null;
985 return; 988 if (part != null)
989 {
990 group = part.ParentGroup;
991 }
992 if (part != null && group != null)
993 {
994 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
995 return;
986 996
987 SceneObjectGroup group = part.ParentGroup; 997 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
988 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 998 if (item == null)
989 return; 999 return;
990
991 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
992 if (item == null)
993 return;
994 1000
995 if (item.Type == 10) 1001 if (item.Type == 10)
996 { 1002 {
997 part.RemoveScriptEvents(itemID); 1003 part.RemoveScriptEvents(itemID);
998 EventManager.TriggerRemoveScript(localID, itemID); 1004 EventManager.TriggerRemoveScript(localID, itemID);
1005 }
1006
1007 group.RemoveInventoryItem(localID, itemID);
1008 part.GetProperties(remoteClient);
999 } 1009 }
1000
1001 group.RemoveInventoryItem(localID, itemID);
1002 part.GetProperties(remoteClient);
1003 } 1010 }
1004 1011
1005 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) 1012 private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId)
@@ -1210,6 +1217,10 @@ namespace OpenSim.Region.Framework.Scenes
1210 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1217 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1211 return; 1218 return;
1212 1219
1220 bool overrideNoMod = false;
1221 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1222 overrideNoMod = true;
1223
1213 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1224 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1214 { 1225 {
1215 // object cannot copy items to an object owned by a different owner 1226 // object cannot copy items to an object owned by a different owner
@@ -1219,7 +1230,7 @@ namespace OpenSim.Region.Framework.Scenes
1219 } 1230 }
1220 1231
1221 // must have both move and modify permission to put an item in an object 1232 // must have both move and modify permission to put an item in an object
1222 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1233 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1223 { 1234 {
1224 return; 1235 return;
1225 } 1236 }
@@ -1278,6 +1289,14 @@ namespace OpenSim.Region.Framework.Scenes
1278 1289
1279 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1290 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1280 { 1291 {
1292 SceneObjectPart destPart = GetSceneObjectPart(destID);
1293 if (destPart != null) // Move into a prim
1294 {
1295 foreach(UUID itemID in items)
1296 MoveTaskInventoryItem(destID, host, itemID);
1297 return destID; // Prim folder ID == prim ID
1298 }
1299
1281 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1300 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1282 1301
1283 UUID newFolderID = UUID.Random(); 1302 UUID newFolderID = UUID.Random();
@@ -1457,13 +1476,6 @@ namespace OpenSim.Region.Framework.Scenes
1457 { 1476 {
1458 agentTransactions.HandleTaskItemUpdateFromTransaction( 1477 agentTransactions.HandleTaskItemUpdateFromTransaction(
1459 remoteClient, part, transactionID, currentItem); 1478 remoteClient, part, transactionID, currentItem);
1460
1461 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1462 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1463 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1464 remoteClient.SendAgentAlertMessage("Script saved", false);
1465 else
1466 remoteClient.SendAgentAlertMessage("Item saved", false);
1467 } 1479 }
1468 1480
1469 // Base ALWAYS has move 1481 // Base ALWAYS has move
@@ -1604,7 +1616,7 @@ namespace OpenSim.Region.Framework.Scenes
1604 return; 1616 return;
1605 1617
1606 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1618 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1607 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1619 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1608 remoteClient.AgentId); 1620 remoteClient.AgentId);
1609 AssetService.Store(asset); 1621 AssetService.Store(asset);
1610 1622
@@ -1757,23 +1769,32 @@ namespace OpenSim.Region.Framework.Scenes
1757 // build a list of eligible objects 1769 // build a list of eligible objects
1758 List<uint> deleteIDs = new List<uint>(); 1770 List<uint> deleteIDs = new List<uint>();
1759 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1771 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1760 1772 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1761 // Start with true for both, then remove the flags if objects
1762 // that we can't derez are part of the selection
1763 bool permissionToTake = true;
1764 bool permissionToTakeCopy = true;
1765 bool permissionToDelete = true;
1766 1773
1767 foreach (uint localID in localIDs) 1774 foreach (uint localID in localIDs)
1768 { 1775 {
1776 // Start with true for both, then remove the flags if objects
1777 // that we can't derez are part of the selection
1778 bool permissionToTake = true;
1779 bool permissionToTakeCopy = true;
1780 bool permissionToDelete = true;
1781
1769 // Invalid id 1782 // Invalid id
1770 SceneObjectPart part = GetSceneObjectPart(localID); 1783 SceneObjectPart part = GetSceneObjectPart(localID);
1771 if (part == null) 1784 if (part == null)
1785 {
1786 //Client still thinks the object exists, kill it
1787 deleteIDs.Add(localID);
1772 continue; 1788 continue;
1789 }
1773 1790
1774 // Already deleted by someone else 1791 // Already deleted by someone else
1775 if (part.ParentGroup.IsDeleted) 1792 if (part.ParentGroup.IsDeleted)
1793 {
1794 //Client still thinks the object exists, kill it
1795 deleteIDs.Add(localID);
1776 continue; 1796 continue;
1797 }
1777 1798
1778 // Can't delete child prims 1799 // Can't delete child prims
1779 if (part != part.ParentGroup.RootPart) 1800 if (part != part.ParentGroup.RootPart)
@@ -1781,9 +1802,6 @@ namespace OpenSim.Region.Framework.Scenes
1781 1802
1782 SceneObjectGroup grp = part.ParentGroup; 1803 SceneObjectGroup grp = part.ParentGroup;
1783 1804
1784 deleteIDs.Add(localID);
1785 deleteGroups.Add(grp);
1786
1787 if (remoteClient == null) 1805 if (remoteClient == null)
1788 { 1806 {
1789 // Autoreturn has a null client. Nothing else does. So 1807 // Autoreturn has a null client. Nothing else does. So
@@ -1800,81 +1818,193 @@ namespace OpenSim.Region.Framework.Scenes
1800 } 1818 }
1801 else 1819 else
1802 { 1820 {
1803 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1821 if (action == DeRezAction.TakeCopy)
1822 {
1823 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1824 permissionToTakeCopy = false;
1825 }
1826 else
1827 {
1804 permissionToTakeCopy = false; 1828 permissionToTakeCopy = false;
1805 1829 }
1806 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1830 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1807 permissionToTake = false; 1831 permissionToTake = false;
1808 1832
1809 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1833 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1810 permissionToDelete = false; 1834 permissionToDelete = false;
1811 } 1835 }
1812 }
1813 1836
1814 // Handle god perms 1837 // Handle god perms
1815 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1838 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1816 { 1839 {
1817 permissionToTake = true; 1840 permissionToTake = true;
1818 permissionToTakeCopy = true; 1841 permissionToTakeCopy = true;
1819 permissionToDelete = true; 1842 permissionToDelete = true;
1820 } 1843 }
1821 1844
1822 // If we're re-saving, we don't even want to delete 1845 // If we're re-saving, we don't even want to delete
1823 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1846 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1824 permissionToDelete = false; 1847 permissionToDelete = false;
1825 1848
1826 // if we want to take a copy, we also don't want to delete 1849 // if we want to take a copy, we also don't want to delete
1827 // Note: after this point, the permissionToTakeCopy flag 1850 // Note: after this point, the permissionToTakeCopy flag
1828 // becomes irrelevant. It already includes the permissionToTake 1851 // becomes irrelevant. It already includes the permissionToTake
1829 // permission and after excluding no copy items here, we can 1852 // permission and after excluding no copy items here, we can
1830 // just use that. 1853 // just use that.
1831 if (action == DeRezAction.TakeCopy) 1854 if (action == DeRezAction.TakeCopy)
1832 { 1855 {
1833 // If we don't have permission, stop right here 1856 // If we don't have permission, stop right here
1834 if (!permissionToTakeCopy) 1857 if (!permissionToTakeCopy)
1835 return; 1858 return;
1836 1859
1837 permissionToTake = true; 1860 permissionToTake = true;
1838 // Don't delete 1861 // Don't delete
1839 permissionToDelete = false; 1862 permissionToDelete = false;
1840 } 1863 }
1841 1864
1842 if (action == DeRezAction.Return) 1865 if (action == DeRezAction.Return)
1843 {
1844 if (remoteClient != null)
1845 { 1866 {
1846 if (Permissions.CanReturnObjects( 1867 if (remoteClient != null)
1847 null,
1848 remoteClient.AgentId,
1849 deleteGroups))
1850 { 1868 {
1851 permissionToTake = true; 1869 if (Permissions.CanReturnObjects(
1852 permissionToDelete = true; 1870 null,
1853 1871 remoteClient.AgentId,
1854 foreach (SceneObjectGroup g in deleteGroups) 1872 deleteGroups))
1855 { 1873 {
1856 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1874 permissionToTake = true;
1875 permissionToDelete = true;
1876
1877 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1857 } 1878 }
1858 } 1879 }
1880 else // Auto return passes through here with null agent
1881 {
1882 permissionToTake = true;
1883 permissionToDelete = true;
1884 }
1859 } 1885 }
1860 else // Auto return passes through here with null agent 1886
1887 if (permissionToTake && (!permissionToDelete))
1888 takeGroups.Add(grp);
1889
1890 if (permissionToDelete)
1861 { 1891 {
1862 permissionToTake = true; 1892 if (permissionToTake)
1863 permissionToDelete = true; 1893 deleteGroups.Add(grp);
1894 deleteIDs.Add(grp.LocalId);
1864 } 1895 }
1865 } 1896 }
1866 1897
1867 if (permissionToTake) 1898 SendKillObject(deleteIDs);
1899
1900 if (deleteGroups.Count > 0)
1868 { 1901 {
1902 foreach (SceneObjectGroup g in deleteGroups)
1903 deleteIDs.Remove(g.LocalId);
1904
1869 m_asyncSceneObjectDeleter.DeleteToInventory( 1905 m_asyncSceneObjectDeleter.DeleteToInventory(
1870 action, destinationID, deleteGroups, remoteClient, 1906 action, destinationID, deleteGroups, remoteClient,
1871 permissionToDelete); 1907 true);
1872 } 1908 }
1873 else if (permissionToDelete) 1909 if (takeGroups.Count > 0)
1910 {
1911 m_asyncSceneObjectDeleter.DeleteToInventory(
1912 action, destinationID, takeGroups, remoteClient,
1913 false);
1914 }
1915 if (deleteIDs.Count > 0)
1874 { 1916 {
1875 foreach (SceneObjectGroup g in deleteGroups) 1917 foreach (SceneObjectGroup g in deleteGroups)
1876 DeleteSceneObject(g, false); 1918 DeleteSceneObject(g, true);
1919 }
1920 }
1921
1922 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
1923 {
1924 itemID = UUID.Zero;
1925 if (grp != null)
1926 {
1927 Vector3 inventoryStoredPosition = new Vector3
1928 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
1929 ? 250
1930 : grp.AbsolutePosition.X)
1931 ,
1932 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
1933 ? 250
1934 : grp.AbsolutePosition.X,
1935 grp.AbsolutePosition.Z);
1936
1937 Vector3 originalPosition = grp.AbsolutePosition;
1938
1939 grp.AbsolutePosition = inventoryStoredPosition;
1940
1941 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
1942
1943 grp.AbsolutePosition = originalPosition;
1944
1945 AssetBase asset = CreateAsset(
1946 grp.GetPartName(grp.LocalId),
1947 grp.GetPartDescription(grp.LocalId),
1948 (sbyte)AssetType.Object,
1949 Utils.StringToBytes(sceneObjectXml),
1950 remoteClient.AgentId);
1951 AssetService.Store(asset);
1952
1953 InventoryItemBase item = new InventoryItemBase();
1954 item.CreatorId = grp.RootPart.CreatorID.ToString();
1955 item.CreatorData = grp.RootPart.CreatorData;
1956 item.Owner = remoteClient.AgentId;
1957 item.ID = UUID.Random();
1958 item.AssetID = asset.FullID;
1959 item.Description = asset.Description;
1960 item.Name = asset.Name;
1961 item.AssetType = asset.Type;
1962 item.InvType = (int)InventoryType.Object;
1963
1964 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
1965 if (folder != null)
1966 item.Folder = folder.ID;
1967 else // oopsies
1968 item.Folder = UUID.Zero;
1969
1970 // Set up base perms properly
1971 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1972 permsBase &= grp.RootPart.BaseMask;
1973 permsBase |= (uint)PermissionMask.Move;
1974
1975 // Make sure we don't lock it
1976 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1977
1978 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1979 {
1980 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1981 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1982 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1983 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1984 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1985 }
1986 else
1987 {
1988 item.BasePermissions = permsBase;
1989 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1990 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1991 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1992 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1993 }
1994 item.CreationDate = Util.UnixTimeSinceEpoch();
1995
1996 // sets itemID so client can show item as 'attached' in inventory
1997 grp.SetFromItemID(item.ID);
1998
1999 if (AddInventoryItem(item))
2000 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2001 else
2002 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2003
2004 itemID = item.ID;
2005 return item.AssetID;
1877 } 2006 }
2007 return UUID.Zero;
1878 } 2008 }
1879 2009
1880 /// <summary> 2010 /// <summary>
@@ -2003,6 +2133,9 @@ namespace OpenSim.Region.Framework.Scenes
2003 2133
2004 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2134 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2005 { 2135 {
2136 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2137 return;
2138
2006 SceneObjectPart part = GetSceneObjectPart(objectID); 2139 SceneObjectPart part = GetSceneObjectPart(objectID);
2007 if (part == null) 2140 if (part == null)
2008 return; 2141 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 29d01d6..9da57a8 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 c5c9260..c5bb2b2 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
@@ -1148,7 +1174,9 @@ namespace OpenSim.Region.Framework.Scenes
1148 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1174 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1149 if (HeartbeatThread != null) 1175 if (HeartbeatThread != null)
1150 { 1176 {
1177 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1151 HeartbeatThread.Abort(); 1178 HeartbeatThread.Abort();
1179 Watchdog.RemoveThread(HeartbeatThread.ManagedThreadId);
1152 HeartbeatThread = null; 1180 HeartbeatThread = null;
1153 } 1181 }
1154 m_lastUpdate = Util.EnvironmentTickCount(); 1182 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1272,9 +1300,6 @@ namespace OpenSim.Region.Framework.Scenes
1272 { 1300 {
1273 while (!shuttingdown) 1301 while (!shuttingdown)
1274 Update(); 1302 Update();
1275
1276 m_lastUpdate = Util.EnvironmentTickCount();
1277 m_firstHeartbeat = false;
1278 } 1303 }
1279 catch (ThreadAbortException) 1304 catch (ThreadAbortException)
1280 { 1305 {
@@ -1380,12 +1405,12 @@ namespace OpenSim.Region.Framework.Scenes
1380 terrainMS = Util.EnvironmentTickCountSubtract(terMS); 1405 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1381 } 1406 }
1382 1407
1383 //if (Frame % m_update_land == 0) 1408 // if (Frame % m_update_land == 0)
1384 //{ 1409 // {
1385 // int ldMS = Util.EnvironmentTickCount(); 1410 // int ldMS = Util.EnvironmentTickCount();
1386 // UpdateLand(); 1411 // UpdateLand();
1387 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1412 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1388 //} 1413 // }
1389 1414
1390 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); 1415 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
1391 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1416 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
@@ -1467,12 +1492,16 @@ namespace OpenSim.Region.Framework.Scenes
1467 maintc = Util.EnvironmentTickCountSubtract(maintc); 1492 maintc = Util.EnvironmentTickCountSubtract(maintc);
1468 maintc = (int)(m_timespan * 1000) - maintc; 1493 maintc = (int)(m_timespan * 1000) - maintc;
1469 1494
1495
1496 m_lastUpdate = Util.EnvironmentTickCount();
1497 m_firstHeartbeat = false;
1498
1470 if (maintc > 0) 1499 if (maintc > 0)
1471 Thread.Sleep(maintc); 1500 Thread.Sleep(maintc);
1472 1501
1473 // Tell the watchdog that this thread is still alive 1502 // Tell the watchdog that this thread is still alive
1474 Watchdog.UpdateThread(); 1503 Watchdog.UpdateThread();
1475 } 1504 }
1476 1505
1477 public void AddGroupTarget(SceneObjectGroup grp) 1506 public void AddGroupTarget(SceneObjectGroup grp)
1478 { 1507 {
@@ -1488,9 +1517,9 @@ namespace OpenSim.Region.Framework.Scenes
1488 1517
1489 private void CheckAtTargets() 1518 private void CheckAtTargets()
1490 { 1519 {
1491 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1520 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1492 lock (m_groupsWithTargets) 1521 lock (m_groupsWithTargets)
1493 objs = m_groupsWithTargets.Values; 1522 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1494 1523
1495 foreach (SceneObjectGroup entry in objs) 1524 foreach (SceneObjectGroup entry in objs)
1496 entry.checkAtTargets(); 1525 entry.checkAtTargets();
@@ -1810,14 +1839,24 @@ namespace OpenSim.Region.Framework.Scenes
1810 /// <returns></returns> 1839 /// <returns></returns>
1811 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1840 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1812 { 1841 {
1842
1843 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1844 Vector3 wpos = Vector3.Zero;
1845 // Check for water surface intersection from above
1846 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1847 {
1848 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1849 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1850 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1851 wpos.Z = wheight;
1852 }
1853
1813 Vector3 pos = Vector3.Zero; 1854 Vector3 pos = Vector3.Zero;
1814 if (RayEndIsIntersection == (byte)1) 1855 if (RayEndIsIntersection == (byte)1)
1815 { 1856 {
1816 pos = RayEnd; 1857 pos = RayEnd;
1817 return pos;
1818 } 1858 }
1819 1859 else if (RayTargetID != UUID.Zero)
1820 if (RayTargetID != UUID.Zero)
1821 { 1860 {
1822 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1861 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1823 1862
@@ -1839,7 +1878,7 @@ namespace OpenSim.Region.Framework.Scenes
1839 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1878 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1840 1879
1841 // Un-comment out the following line to Get Raytrace results printed to the console. 1880 // Un-comment out the following line to Get Raytrace results printed to the console.
1842 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1881 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1843 float ScaleOffset = 0.5f; 1882 float ScaleOffset = 0.5f;
1844 1883
1845 // If we hit something 1884 // If we hit something
@@ -1862,13 +1901,10 @@ namespace OpenSim.Region.Framework.Scenes
1862 //pos.Z -= 0.25F; 1901 //pos.Z -= 0.25F;
1863 1902
1864 } 1903 }
1865
1866 return pos;
1867 } 1904 }
1868 else 1905 else
1869 { 1906 {
1870 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1907 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1871
1872 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1908 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1873 1909
1874 // Un-comment the following line to print the raytrace results to the console. 1910 // Un-comment the following line to print the raytrace results to the console.
@@ -1877,13 +1913,12 @@ namespace OpenSim.Region.Framework.Scenes
1877 if (ei.HitTF) 1913 if (ei.HitTF)
1878 { 1914 {
1879 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1915 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1880 } else 1916 }
1917 else
1881 { 1918 {
1882 // fall back to our stupid functionality 1919 // fall back to our stupid functionality
1883 pos = RayEnd; 1920 pos = RayEnd;
1884 } 1921 }
1885
1886 return pos;
1887 } 1922 }
1888 } 1923 }
1889 else 1924 else
@@ -1894,8 +1929,12 @@ namespace OpenSim.Region.Framework.Scenes
1894 //increase height so its above the ground. 1929 //increase height so its above the ground.
1895 //should be getting the normal of the ground at the rez point and using that? 1930 //should be getting the normal of the ground at the rez point and using that?
1896 pos.Z += scale.Z / 2f; 1931 pos.Z += scale.Z / 2f;
1897 return pos; 1932// return pos;
1898 } 1933 }
1934
1935 // check against posible water intercept
1936 if (wpos.Z > pos.Z) pos = wpos;
1937 return pos;
1899 } 1938 }
1900 1939
1901 1940
@@ -1979,7 +2018,10 @@ namespace OpenSim.Region.Framework.Scenes
1979 public bool AddRestoredSceneObject( 2018 public bool AddRestoredSceneObject(
1980 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2019 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1981 { 2020 {
1982 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2021 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
2022 if (result)
2023 sceneObject.IsDeleted = false;
2024 return result;
1983 } 2025 }
1984 2026
1985 /// <summary> 2027 /// <summary>
@@ -2069,6 +2111,15 @@ namespace OpenSim.Region.Framework.Scenes
2069 /// </summary> 2111 /// </summary>
2070 public void DeleteAllSceneObjects() 2112 public void DeleteAllSceneObjects()
2071 { 2113 {
2114 DeleteAllSceneObjects(false);
2115 }
2116
2117 /// <summary>
2118 /// Delete every object from the scene. This does not include attachments worn by avatars.
2119 /// </summary>
2120 public void DeleteAllSceneObjects(bool exceptNoCopy)
2121 {
2122 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2072 lock (Entities) 2123 lock (Entities)
2073 { 2124 {
2074 EntityBase[] entities = Entities.GetEntities(); 2125 EntityBase[] entities = Entities.GetEntities();
@@ -2077,11 +2128,24 @@ namespace OpenSim.Region.Framework.Scenes
2077 if (e is SceneObjectGroup) 2128 if (e is SceneObjectGroup)
2078 { 2129 {
2079 SceneObjectGroup sog = (SceneObjectGroup)e; 2130 SceneObjectGroup sog = (SceneObjectGroup)e;
2080 if (!sog.IsAttachment) 2131 if (sog != null && !sog.IsAttachment)
2081 DeleteSceneObject((SceneObjectGroup)e, false); 2132 {
2133 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2134 {
2135 DeleteSceneObject((SceneObjectGroup)e, false);
2136 }
2137 else
2138 {
2139 toReturn.Add((SceneObjectGroup)e);
2140 }
2141 }
2082 } 2142 }
2083 } 2143 }
2084 } 2144 }
2145 if (toReturn.Count > 0)
2146 {
2147 returnObjects(toReturn.ToArray(), UUID.Zero);
2148 }
2085 } 2149 }
2086 2150
2087 /// <summary> 2151 /// <summary>
@@ -2130,6 +2194,8 @@ namespace OpenSim.Region.Framework.Scenes
2130 } 2194 }
2131 2195
2132 group.DeleteGroupFromScene(silent); 2196 group.DeleteGroupFromScene(silent);
2197 if (!silent)
2198 SendKillObject(new List<uint>() { group.LocalId });
2133 2199
2134// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2200// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2135 } 2201 }
@@ -2484,10 +2550,17 @@ namespace OpenSim.Region.Framework.Scenes
2484 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2550 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2485 public bool AddSceneObject(SceneObjectGroup sceneObject) 2551 public bool AddSceneObject(SceneObjectGroup sceneObject)
2486 { 2552 {
2553 if (sceneObject.OwnerID == UUID.Zero)
2554 {
2555 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2556 return false;
2557 }
2558
2487 // If the user is banned, we won't let any of their objects 2559 // If the user is banned, we won't let any of their objects
2488 // enter. Period. 2560 // enter. Period.
2489 // 2561 //
2490 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2562 int flags = GetUserFlags(sceneObject.OwnerID);
2563 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2491 { 2564 {
2492 m_log.Info("[INTERREGION]: Denied prim crossing for " + 2565 m_log.Info("[INTERREGION]: Denied prim crossing for " +
2493 "banned avatar"); 2566 "banned avatar");
@@ -2531,15 +2604,28 @@ namespace OpenSim.Region.Framework.Scenes
2531 2604
2532 if (AttachmentsModule != null) 2605 if (AttachmentsModule != null)
2533 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2606 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2607
2608 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2534 } 2609 }
2535 else 2610 else
2536 { 2611 {
2612 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2537 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2613 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2538 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2614 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2539 } 2615 }
2616 if (sceneObject.OwnerID == UUID.Zero)
2617 {
2618 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2619 return false;
2620 }
2540 } 2621 }
2541 else 2622 else
2542 { 2623 {
2624 if (sceneObject.OwnerID == UUID.Zero)
2625 {
2626 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2627 return false;
2628 }
2543 AddRestoredSceneObject(sceneObject, true, false); 2629 AddRestoredSceneObject(sceneObject, true, false);
2544 2630
2545 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2631 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2569,6 +2655,24 @@ namespace OpenSim.Region.Framework.Scenes
2569 return 2; // StateSource.PrimCrossing 2655 return 2; // StateSource.PrimCrossing
2570 } 2656 }
2571 2657
2658 public int GetUserFlags(UUID user)
2659 {
2660 //Unfortunately the SP approach means that the value is cached until region is restarted
2661 /*
2662 ScenePresence sp;
2663 if (TryGetScenePresence(user, out sp))
2664 {
2665 return sp.UserFlags;
2666 }
2667 else
2668 {
2669 */
2670 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2671 if (uac == null)
2672 return 0;
2673 return uac.UserFlags;
2674 //}
2675 }
2572 #endregion 2676 #endregion
2573 2677
2574 #region Add/Remove Avatar Methods 2678 #region Add/Remove Avatar Methods
@@ -2590,6 +2694,7 @@ namespace OpenSim.Region.Framework.Scenes
2590 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2694 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2591 2695
2592 CheckHeartbeat(); 2696 CheckHeartbeat();
2697 ScenePresence presence;
2593 2698
2594 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here 2699 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here
2595 { 2700 {
@@ -2623,7 +2728,14 @@ namespace OpenSim.Region.Framework.Scenes
2623 2728
2624 EventManager.TriggerOnNewClient(client); 2729 EventManager.TriggerOnNewClient(client);
2625 if (vialogin) 2730 if (vialogin)
2731 {
2626 EventManager.TriggerOnClientLogin(client); 2732 EventManager.TriggerOnClientLogin(client);
2733
2734 // Send initial parcel data
2735 Vector3 pos = createdSp.AbsolutePosition;
2736 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2737 land.SendLandUpdateToClient(client);
2738 }
2627 } 2739 }
2628 } 2740 }
2629 2741
@@ -2712,19 +2824,12 @@ namespace OpenSim.Region.Framework.Scenes
2712 // and the scene presence and the client, if they exist 2824 // and the scene presence and the client, if they exist
2713 try 2825 try
2714 { 2826 {
2715 // We need to wait for the client to make UDP contact first. 2827 ScenePresence sp = GetScenePresence(agentID);
2716 // It's the UDP contact that creates the scene presence 2828 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2717 ScenePresence sp = WaitGetScenePresence(agentID); 2829
2718 if (sp != null) 2830 if (sp != null)
2719 {
2720 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2721
2722 sp.ControllingClient.Close(); 2831 sp.ControllingClient.Close();
2723 } 2832
2724 else
2725 {
2726 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2727 }
2728 // BANG! SLASH! 2833 // BANG! SLASH!
2729 m_authenticateHandler.RemoveCircuit(agentID); 2834 m_authenticateHandler.RemoveCircuit(agentID);
2730 2835
@@ -2824,6 +2929,7 @@ namespace OpenSim.Region.Framework.Scenes
2824 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2929 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2825 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2930 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2826 client.OnCopyInventoryItem += CopyInventoryItem; 2931 client.OnCopyInventoryItem += CopyInventoryItem;
2932 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2827 client.OnMoveInventoryItem += MoveInventoryItem; 2933 client.OnMoveInventoryItem += MoveInventoryItem;
2828 client.OnRemoveInventoryItem += RemoveInventoryItem; 2934 client.OnRemoveInventoryItem += RemoveInventoryItem;
2829 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2935 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -3001,15 +3107,16 @@ namespace OpenSim.Region.Framework.Scenes
3001 /// </summary> 3107 /// </summary>
3002 /// <param name="agentId">The avatar's Unique ID</param> 3108 /// <param name="agentId">The avatar's Unique ID</param>
3003 /// <param name="client">The IClientAPI for the client</param> 3109 /// <param name="client">The IClientAPI for the client</param>
3004 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3110 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
3005 { 3111 {
3006 if (m_teleportModule != null) 3112 if (m_teleportModule != null)
3007 m_teleportModule.TeleportHome(agentId, client); 3113 return m_teleportModule.TeleportHome(agentId, client);
3008 else 3114 else
3009 { 3115 {
3010 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3116 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
3011 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3117 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
3012 } 3118 }
3119 return false;
3013 } 3120 }
3014 3121
3015 /// <summary> 3122 /// <summary>
@@ -3101,6 +3208,16 @@ namespace OpenSim.Region.Framework.Scenes
3101 /// <param name="flags"></param> 3208 /// <param name="flags"></param>
3102 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3209 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3103 { 3210 {
3211 //Add half the avatar's height so that the user doesn't fall through prims
3212 ScenePresence presence;
3213 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3214 {
3215 if (presence.Appearance != null)
3216 {
3217 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3218 }
3219 }
3220
3104 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3221 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3105 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3222 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3106 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3223 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3175,8 +3292,9 @@ namespace OpenSim.Region.Framework.Scenes
3175 regions.Remove(RegionInfo.RegionHandle); 3292 regions.Remove(RegionInfo.RegionHandle);
3176 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3293 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3177 } 3294 }
3178 3295 m_log.Debug("[Scene] Beginning ClientClosed");
3179 m_eventManager.TriggerClientClosed(agentID, this); 3296 m_eventManager.TriggerClientClosed(agentID, this);
3297 m_log.Debug("[Scene] Finished ClientClosed");
3180 } 3298 }
3181 catch (NullReferenceException) 3299 catch (NullReferenceException)
3182 { 3300 {
@@ -3184,7 +3302,12 @@ namespace OpenSim.Region.Framework.Scenes
3184 // Avatar is already disposed :/ 3302 // Avatar is already disposed :/
3185 } 3303 }
3186 3304
3305 m_log.Debug("[Scene] Beginning OnRemovePresence");
3187 m_eventManager.TriggerOnRemovePresence(agentID); 3306 m_eventManager.TriggerOnRemovePresence(agentID);
3307 m_log.Debug("[Scene] Finished OnRemovePresence");
3308
3309 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
3310 AttachmentsModule.SaveChangedAttachments(avatar);
3188 3311
3189 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc) 3312 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
3190 AttachmentsModule.SaveChangedAttachments(avatar); 3313 AttachmentsModule.SaveChangedAttachments(avatar);
@@ -3193,7 +3316,7 @@ namespace OpenSim.Region.Framework.Scenes
3193 delegate(IClientAPI client) 3316 delegate(IClientAPI client)
3194 { 3317 {
3195 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3318 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3196 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3319 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3197 catch (NullReferenceException) { } 3320 catch (NullReferenceException) { }
3198 }); 3321 });
3199 3322
@@ -3204,8 +3327,11 @@ namespace OpenSim.Region.Framework.Scenes
3204 } 3327 }
3205 3328
3206 // Remove the avatar from the scene 3329 // Remove the avatar from the scene
3330 m_log.Debug("[Scene] Begin RemoveScenePresence");
3207 m_sceneGraph.RemoveScenePresence(agentID); 3331 m_sceneGraph.RemoveScenePresence(agentID);
3332 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3208 m_clientManager.Remove(agentID); 3333 m_clientManager.Remove(agentID);
3334 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3209 3335
3210 try 3336 try
3211 { 3337 {
@@ -3219,9 +3345,10 @@ namespace OpenSim.Region.Framework.Scenes
3219 { 3345 {
3220 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3346 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3221 } 3347 }
3222 3348 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3223 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3349 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3224// CleanDroppedAttachments(); 3350// CleanDroppedAttachments();
3351 m_log.Debug("[Scene] The avatar has left the building");
3225 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3352 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3226 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3353 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3227 } 3354 }
@@ -3252,19 +3379,24 @@ namespace OpenSim.Region.Framework.Scenes
3252 3379
3253 #region Entities 3380 #region Entities
3254 3381
3255 public void SendKillObject(uint localID) 3382 public void SendKillObject(List<uint> localIDs)
3256 { 3383 {
3257 SceneObjectPart part = GetSceneObjectPart(localID); 3384 List<uint> deleteIDs = new List<uint>();
3258 if (part != null) // It is a prim 3385
3386 foreach (uint localID in localIDs)
3259 { 3387 {
3260 if (!part.ParentGroup.IsDeleted) // Valid 3388 SceneObjectPart part = GetSceneObjectPart(localID);
3389 if (part != null) // It is a prim
3261 { 3390 {
3262 if (part.ParentGroup.RootPart != part) // Child part 3391 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3263 return; 3392 {
3393 if (part.ParentGroup.RootPart != part) // Child part
3394 continue;
3395 }
3264 } 3396 }
3397 deleteIDs.Add(localID);
3265 } 3398 }
3266 3399 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3267 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); });
3268 } 3400 }
3269 3401
3270 #endregion 3402 #endregion
@@ -3282,7 +3414,6 @@ namespace OpenSim.Region.Framework.Scenes
3282 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3414 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3283 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3415 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3284 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3416 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3285 m_sceneGridService.KiPrimitive += SendKillObject;
3286 m_sceneGridService.OnGetLandData += GetLandData; 3417 m_sceneGridService.OnGetLandData += GetLandData;
3287 } 3418 }
3288 3419
@@ -3291,7 +3422,6 @@ namespace OpenSim.Region.Framework.Scenes
3291 /// </summary> 3422 /// </summary>
3292 public void UnRegisterRegionWithComms() 3423 public void UnRegisterRegionWithComms()
3293 { 3424 {
3294 m_sceneGridService.KiPrimitive -= SendKillObject;
3295 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3425 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3296 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3426 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3297 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3427 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3371,13 +3501,16 @@ namespace OpenSim.Region.Framework.Scenes
3371 sp = null; 3501 sp = null;
3372 } 3502 }
3373 3503
3374 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3375 3504
3376 //On login test land permisions 3505 //On login test land permisions
3377 if (vialogin) 3506 if (vialogin)
3378 { 3507 {
3379 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3508 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3509 if (cache != null)
3510 cache.Remove(agent.firstname + " " + agent.lastname);
3511 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3380 { 3512 {
3513 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3381 return false; 3514 return false;
3382 } 3515 }
3383 } 3516 }
@@ -3400,8 +3533,13 @@ namespace OpenSim.Region.Framework.Scenes
3400 3533
3401 try 3534 try
3402 { 3535 {
3403 if (!AuthorizeUser(agent, out reason)) 3536 // Always check estate if this is a login. Always
3404 return false; 3537 // check if banned regions are to be blacked out.
3538 if (vialogin || (!m_seeIntoBannedRegion))
3539 {
3540 if (!AuthorizeUser(agent, out reason))
3541 return false;
3542 }
3405 } 3543 }
3406 catch (Exception e) 3544 catch (Exception e)
3407 { 3545 {
@@ -3503,6 +3641,8 @@ namespace OpenSim.Region.Framework.Scenes
3503 } 3641 }
3504 } 3642 }
3505 // Honor parcel landing type and position. 3643 // Honor parcel landing type and position.
3644 /*
3645 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3506 if (land != null) 3646 if (land != null)
3507 { 3647 {
3508 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3648 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3510,26 +3650,34 @@ namespace OpenSim.Region.Framework.Scenes
3510 agent.startpos = land.LandData.UserLocation; 3650 agent.startpos = land.LandData.UserLocation;
3511 } 3651 }
3512 } 3652 }
3653 */// This is now handled properly in ScenePresence.MakeRootAgent
3513 } 3654 }
3514 3655
3515 return true; 3656 return true;
3516 } 3657 }
3517 3658
3518 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3659 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3519 { 3660 {
3520 3661 reason = String.Empty;
3521 bool banned = land.IsBannedFromLand(agent.AgentID); 3662 if (Permissions.IsGod(agentID))
3522 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3663 return true;
3664
3665 ILandObject land = LandChannel.GetLandObject(posX, posY);
3666 if (land == null)
3667 return false;
3668
3669 bool banned = land.IsBannedFromLand(agentID);
3670 bool restricted = land.IsRestrictedFromLand(agentID);
3523 3671
3524 if (banned || restricted) 3672 if (banned || restricted)
3525 { 3673 {
3526 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3674 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3527 if (nearestParcel != null) 3675 if (nearestParcel != null)
3528 { 3676 {
3529 //Move agent to nearest allowed 3677 //Move agent to nearest allowed
3530 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3678 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3531 agent.startpos.X = newPosition.X; 3679 posX = newPosition.X;
3532 agent.startpos.Y = newPosition.Y; 3680 posY = newPosition.Y;
3533 } 3681 }
3534 else 3682 else
3535 { 3683 {
@@ -3591,7 +3739,7 @@ namespace OpenSim.Region.Framework.Scenes
3591 3739
3592 if (!m_strictAccessControl) return true; 3740 if (!m_strictAccessControl) return true;
3593 if (Permissions.IsGod(agent.AgentID)) return true; 3741 if (Permissions.IsGod(agent.AgentID)) return true;
3594 3742
3595 if (AuthorizationService != null) 3743 if (AuthorizationService != null)
3596 { 3744 {
3597 if (!AuthorizationService.IsAuthorizedForRegion( 3745 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3599,14 +3747,14 @@ namespace OpenSim.Region.Framework.Scenes
3599 { 3747 {
3600 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3748 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3601 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3749 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3602 3750
3603 return false; 3751 return false;
3604 } 3752 }
3605 } 3753 }
3606 3754
3607 if (m_regInfo.EstateSettings != null) 3755 if (m_regInfo.EstateSettings != null)
3608 { 3756 {
3609 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3757 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3610 { 3758 {
3611 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3759 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3612 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3760 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3796,6 +3944,13 @@ namespace OpenSim.Region.Framework.Scenes
3796 3944
3797 // We have to wait until the viewer contacts this region after receiving EAC. 3945 // We have to wait until the viewer contacts this region after receiving EAC.
3798 // That calls AddNewClient, which finally creates the ScenePresence 3946 // That calls AddNewClient, which finally creates the ScenePresence
3947 int flags = GetUserFlags(cAgentData.AgentID);
3948 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3949 {
3950 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3951 return false;
3952 }
3953
3799 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3954 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3800 if (nearestParcel == null) 3955 if (nearestParcel == null)
3801 { 3956 {
@@ -3811,7 +3966,6 @@ namespace OpenSim.Region.Framework.Scenes
3811 return false; 3966 return false;
3812 } 3967 }
3813 3968
3814
3815 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3969 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3816 3970
3817 if (childAgentUpdate != null) 3971 if (childAgentUpdate != null)
@@ -3878,12 +4032,22 @@ namespace OpenSim.Region.Framework.Scenes
3878 return false; 4032 return false;
3879 } 4033 }
3880 4034
4035 public bool IncomingCloseAgent(UUID agentID)
4036 {
4037 return IncomingCloseAgent(agentID, false);
4038 }
4039
4040 public bool IncomingCloseChildAgent(UUID agentID)
4041 {
4042 return IncomingCloseAgent(agentID, true);
4043 }
4044
3881 /// <summary> 4045 /// <summary>
3882 /// Tell a single agent to disconnect from the region. 4046 /// Tell a single agent to disconnect from the region.
3883 /// </summary> 4047 /// </summary>
3884 /// <param name="regionHandle"></param>
3885 /// <param name="agentID"></param> 4048 /// <param name="agentID"></param>
3886 public bool IncomingCloseAgent(UUID agentID) 4049 /// <param name="childOnly"></param>
4050 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3887 { 4051 {
3888 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4052 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3889 4053
@@ -3895,7 +4059,7 @@ namespace OpenSim.Region.Framework.Scenes
3895 { 4059 {
3896 m_sceneGraph.removeUserCount(false); 4060 m_sceneGraph.removeUserCount(false);
3897 } 4061 }
3898 else 4062 else if (!childOnly)
3899 { 4063 {
3900 m_sceneGraph.removeUserCount(true); 4064 m_sceneGraph.removeUserCount(true);
3901 } 4065 }
@@ -3911,9 +4075,12 @@ namespace OpenSim.Region.Framework.Scenes
3911 } 4075 }
3912 else 4076 else
3913 presence.ControllingClient.SendShutdownConnectionNotice(); 4077 presence.ControllingClient.SendShutdownConnectionNotice();
4078 presence.ControllingClient.Close(false);
4079 }
4080 else if (!childOnly)
4081 {
4082 presence.ControllingClient.Close(true);
3914 } 4083 }
3915
3916 presence.ControllingClient.Close();
3917 return true; 4084 return true;
3918 } 4085 }
3919 4086
@@ -4528,34 +4695,66 @@ namespace OpenSim.Region.Framework.Scenes
4528 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4695 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4529 } 4696 }
4530 4697
4531 public int GetHealth() 4698 public int GetHealth(out int flags, out string message)
4532 { 4699 {
4533 // Returns: 4700 // Returns:
4534 // 1 = sim is up and accepting http requests. The heartbeat has 4701 // 1 = sim is up and accepting http requests. The heartbeat has
4535 // stopped and the sim is probably locked up, but a remote 4702 // stopped and the sim is probably locked up, but a remote
4536 // admin restart may succeed 4703 // admin restart may succeed
4537 // 4704 //
4538 // 2 = Sim is up and the heartbeat is running. The sim is likely 4705 // 2 = Sim is up and the heartbeat is running. The sim is likely
4539 // usable for people within and logins _may_ work 4706 // usable for people within
4707 //
4708 // 3 = Sim is up and one packet thread is running. Sim is
4709 // unstable and will not accept new logins
4540 // 4710 //
4541 // 3 = We have seen a new user enter within the past 4 minutes 4711 // 4 = Sim is up and both packet threads are running. Sim is
4712 // likely usable
4713 //
4714 // 5 = We have seen a new user enter within the past 4 minutes
4542 // which can be seen as positive confirmation of sim health 4715 // which can be seen as positive confirmation of sim health
4543 // 4716 //
4717
4718 flags = 0;
4719 message = String.Empty;
4720
4721 CheckHeartbeat();
4722
4723 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4724 {
4725 // We're still starting
4726 // 0 means "in startup", it can't happen another way, since
4727 // to get here, we must be able to accept http connections
4728 return 0;
4729 }
4730
4544 int health=1; // Start at 1, means we're up 4731 int health=1; // Start at 1, means we're up
4545 4732
4546 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4733 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4734 {
4547 health+=1; 4735 health+=1;
4548 else 4736 flags |= 1;
4737 }
4738
4739 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4740 {
4741 health+=1;
4742 flags |= 2;
4743 }
4744
4745 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4746 {
4747 health+=1;
4748 flags |= 4;
4749 }
4750
4751 if (flags != 7)
4549 return health; 4752 return health;
4550 4753
4551 // A login in the last 4 mins? We can't be doing too badly 4754 // A login in the last 4 mins? We can't be doing too badly
4552 // 4755 //
4553 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4756 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4554 health++; 4757 health++;
4555 else
4556 return health;
4557
4558 CheckHeartbeat();
4559 4758
4560 return health; 4759 return health;
4561 } 4760 }
@@ -4748,7 +4947,7 @@ namespace OpenSim.Region.Framework.Scenes
4748 if (m_firstHeartbeat) 4947 if (m_firstHeartbeat)
4749 return; 4948 return;
4750 4949
4751 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4950 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4752 StartTimer(); 4951 StartTimer();
4753 } 4952 }
4754 4953
@@ -5197,6 +5396,19 @@ namespace OpenSim.Region.Framework.Scenes
5197// } 5396// }
5198// } 5397// }
5199 5398
5399 public void ThreadAlive(int threadCode)
5400 {
5401 switch(threadCode)
5402 {
5403 case 1: // Incoming
5404 m_lastIncoming = Util.EnvironmentTickCount();
5405 break;
5406 case 2: // Incoming
5407 m_lastOutgoing = Util.EnvironmentTickCount();
5408 break;
5409 }
5410 }
5411
5200 // This method is called across the simulation connector to 5412 // This method is called across the simulation connector to
5201 // determine if a given agent is allowed in this region 5413 // determine if a given agent is allowed in this region
5202 // AS A ROOT AGENT. Returning false here will prevent them 5414 // AS A ROOT AGENT. Returning false here will prevent them
@@ -5205,6 +5417,14 @@ namespace OpenSim.Region.Framework.Scenes
5205 // child agent creation, thereby emulating the SL behavior. 5417 // child agent creation, thereby emulating the SL behavior.
5206 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5418 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5207 { 5419 {
5420 reason = "You are banned from the region";
5421
5422 if (Permissions.IsGod(agentID))
5423 {
5424 reason = String.Empty;
5425 return true;
5426 }
5427
5208 int num = m_sceneGraph.GetNumberOfScenePresences(); 5428 int num = m_sceneGraph.GetNumberOfScenePresences();
5209 5429
5210 if (num >= RegionInfo.RegionSettings.AgentLimit) 5430 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5216,8 +5436,58 @@ namespace OpenSim.Region.Framework.Scenes
5216 } 5436 }
5217 } 5437 }
5218 5438
5439 try
5440 {
5441 if (!AuthorizeUser(GetScenePresence(agentID).ControllingClient.RequestClientInfo(), out reason))
5442 {
5443 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5444 return false;
5445 }
5446 }
5447 catch
5448 {
5449 return false;
5450 }
5451
5452 if (position == Vector3.Zero) // Teleport
5453 {
5454 float posX = 128.0f;
5455 float posY = 128.0f;
5456
5457 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5458 {
5459 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5460 return false;
5461 }
5462 }
5463 else // Walking
5464 {
5465 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5466 if (land == null)
5467 return false;
5468
5469 bool banned = land.IsBannedFromLand(agentID);
5470 bool restricted = land.IsRestrictedFromLand(agentID);
5471
5472 if (banned || restricted)
5473 return false;
5474 }
5475
5219 reason = String.Empty; 5476 reason = String.Empty;
5220 return true; 5477 return true;
5221 } 5478 }
5479
5480 public void StartTimerWatchdog()
5481 {
5482 m_timerWatchdog.Interval = 1000;
5483 m_timerWatchdog.Elapsed += TimerWatchdog;
5484 m_timerWatchdog.AutoReset = true;
5485 m_timerWatchdog.Start();
5486 }
5487
5488 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5489 {
5490 CheckHeartbeat();
5491 }
5222 } 5492 }
5223} 5493}
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 2819545..ea6aab0 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,13 +1486,11 @@ namespace OpenSim.Region.Framework.Scenes
1171 avatar.StandUp(); 1486 avatar.StandUp();
1172 1487
1173 if (!silent) 1488 if (!silent)
1174 {
1175 part.UpdateFlag = 0; 1489 part.UpdateFlag = 0;
1176 if (part == m_rootPart)
1177 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1178 }
1179 }); 1490 });
1180 } 1491 }
1492
1493
1181 } 1494 }
1182 1495
1183 public void AddScriptLPS(int count) 1496 public void AddScriptLPS(int count)
@@ -1274,7 +1587,12 @@ namespace OpenSim.Region.Framework.Scenes
1274 1587
1275 public void SetOwnerId(UUID userId) 1588 public void SetOwnerId(UUID userId)
1276 { 1589 {
1277 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1590 ForEachPart(delegate(SceneObjectPart part)
1591 {
1592
1593 part.OwnerID = userId;
1594
1595 });
1278 } 1596 }
1279 1597
1280 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1598 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1306,11 +1624,17 @@ namespace OpenSim.Region.Framework.Scenes
1306 return; 1624 return;
1307 } 1625 }
1308 1626
1627 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1628 return;
1629
1309 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1630 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1310 // any exception propogate upwards. 1631 // any exception propogate upwards.
1311 try 1632 try
1312 { 1633 {
1313 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1634 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1635 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1636 m_scene.LoadingPrims) // Land may not be valid yet
1637
1314 { 1638 {
1315 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1639 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1316 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1640 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1337,6 +1661,7 @@ namespace OpenSim.Region.Framework.Scenes
1337 } 1661 }
1338 } 1662 }
1339 } 1663 }
1664
1340 } 1665 }
1341 1666
1342 if (m_scene.UseBackup && HasGroupChanged) 1667 if (m_scene.UseBackup && HasGroupChanged)
@@ -1344,6 +1669,20 @@ namespace OpenSim.Region.Framework.Scenes
1344 // don't backup while it's selected or you're asking for changes mid stream. 1669 // don't backup while it's selected or you're asking for changes mid stream.
1345 if (isTimeToPersist() || forcedBackup) 1670 if (isTimeToPersist() || forcedBackup)
1346 { 1671 {
1672 if (m_rootPart.PhysActor != null &&
1673 (!m_rootPart.PhysActor.IsPhysical))
1674 {
1675 // Possible ghost prim
1676 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1677 {
1678 foreach (SceneObjectPart part in m_parts.GetArray())
1679 {
1680 // Re-set physics actor positions and
1681 // orientations
1682 part.GroupPosition = m_rootPart.GroupPosition;
1683 }
1684 }
1685 }
1347// m_log.DebugFormat( 1686// m_log.DebugFormat(
1348// "[SCENE]: Storing {0}, {1} in {2}", 1687// "[SCENE]: Storing {0}, {1} in {2}",
1349// Name, UUID, m_scene.RegionInfo.RegionName); 1688// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1421,7 +1760,7 @@ namespace OpenSim.Region.Framework.Scenes
1421 // This is only necessary when userExposed is false! 1760 // This is only necessary when userExposed is false!
1422 1761
1423 bool previousAttachmentStatus = dupe.IsAttachment; 1762 bool previousAttachmentStatus = dupe.IsAttachment;
1424 1763
1425 if (!userExposed) 1764 if (!userExposed)
1426 dupe.IsAttachment = true; 1765 dupe.IsAttachment = true;
1427 1766
@@ -1439,11 +1778,11 @@ namespace OpenSim.Region.Framework.Scenes
1439 dupe.m_rootPart.TrimPermissions(); 1778 dupe.m_rootPart.TrimPermissions();
1440 1779
1441 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1780 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1442 1781
1443 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 1782 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1444 { 1783 {
1445 return p1.LinkNum.CompareTo(p2.LinkNum); 1784 return p1.LinkNum.CompareTo(p2.LinkNum);
1446 } 1785 }
1447 ); 1786 );
1448 1787
1449 foreach (SceneObjectPart part in partList) 1788 foreach (SceneObjectPart part in partList)
@@ -1463,7 +1802,7 @@ namespace OpenSim.Region.Framework.Scenes
1463 if (part.PhysActor != null && userExposed) 1802 if (part.PhysActor != null && userExposed)
1464 { 1803 {
1465 PrimitiveBaseShape pbs = newPart.Shape; 1804 PrimitiveBaseShape pbs = newPart.Shape;
1466 1805
1467 newPart.PhysActor 1806 newPart.PhysActor
1468 = m_scene.PhysicsScene.AddPrimShape( 1807 = m_scene.PhysicsScene.AddPrimShape(
1469 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 1808 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
@@ -1473,11 +1812,11 @@ namespace OpenSim.Region.Framework.Scenes
1473 newPart.RotationOffset, 1812 newPart.RotationOffset,
1474 part.PhysActor.IsPhysical, 1813 part.PhysActor.IsPhysical,
1475 newPart.LocalId); 1814 newPart.LocalId);
1476 1815
1477 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1816 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1478 } 1817 }
1479 } 1818 }
1480 1819
1481 if (userExposed) 1820 if (userExposed)
1482 { 1821 {
1483 dupe.UpdateParentIDs(); 1822 dupe.UpdateParentIDs();
@@ -1592,6 +1931,7 @@ namespace OpenSim.Region.Framework.Scenes
1592 return Vector3.Zero; 1931 return Vector3.Zero;
1593 } 1932 }
1594 1933
1934 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1595 public void moveToTarget(Vector3 target, float tau) 1935 public void moveToTarget(Vector3 target, float tau)
1596 { 1936 {
1597 if (IsAttachment) 1937 if (IsAttachment)
@@ -1619,10 +1959,44 @@ namespace OpenSim.Region.Framework.Scenes
1619 RootPart.PhysActor.PIDActive = false; 1959 RootPart.PhysActor.PIDActive = false;
1620 } 1960 }
1621 1961
1962 public void rotLookAt(Quaternion target, float strength, float damping)
1963 {
1964 SceneObjectPart rootpart = m_rootPart;
1965 if (rootpart != null)
1966 {
1967 if (IsAttachment)
1968 {
1969 /*
1970 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1971 if (avatar != null)
1972 {
1973 Rotate the Av?
1974 } */
1975 }
1976 else
1977 {
1978 if (rootpart.PhysActor != null)
1979 { // APID must be implemented in your physics system for this to function.
1980 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1981 rootpart.PhysActor.APIDStrength = strength;
1982 rootpart.PhysActor.APIDDamping = damping;
1983 rootpart.PhysActor.APIDActive = true;
1984 }
1985 }
1986 }
1987 }
1988
1622 public void stopLookAt() 1989 public void stopLookAt()
1623 { 1990 {
1624 if (RootPart.PhysActor != null) 1991 SceneObjectPart rootpart = m_rootPart;
1625 RootPart.PhysActor.APIDActive = false; 1992 if (rootpart != null)
1993 {
1994 if (rootpart.PhysActor != null)
1995 { // APID must be implemented in your physics system for this to function.
1996 rootpart.PhysActor.APIDActive = false;
1997 }
1998 }
1999
1626 } 2000 }
1627 2001
1628 /// <summary> 2002 /// <summary>
@@ -1680,6 +2054,8 @@ namespace OpenSim.Region.Framework.Scenes
1680 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2054 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1681 { 2055 {
1682 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2056 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2057 newPart.SetParent(this);
2058
1683 AddPart(newPart); 2059 AddPart(newPart);
1684 2060
1685 SetPartAsNonRoot(newPart); 2061 SetPartAsNonRoot(newPart);
@@ -1828,11 +2204,11 @@ namespace OpenSim.Region.Framework.Scenes
1828 /// Immediately send a full update for this scene object. 2204 /// Immediately send a full update for this scene object.
1829 /// </summary> 2205 /// </summary>
1830 public void SendGroupFullUpdate() 2206 public void SendGroupFullUpdate()
1831 { 2207 {
1832 if (IsDeleted) 2208 if (IsDeleted)
1833 return; 2209 return;
1834 2210
1835// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2211// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1836 2212
1837 RootPart.SendFullUpdateToAllClients(); 2213 RootPart.SendFullUpdateToAllClients();
1838 2214
@@ -2021,12 +2397,15 @@ namespace OpenSim.Region.Framework.Scenes
2021 part.LinkNum += objectGroup.PrimCount; 2397 part.LinkNum += objectGroup.PrimCount;
2022 } 2398 }
2023 } 2399 }
2400 }
2024 2401
2025 linkPart.LinkNum = 2; 2402 linkPart.LinkNum = 2;
2026 2403
2027 linkPart.SetParent(this); 2404 linkPart.SetParent(this);
2028 linkPart.CreateSelected = true; 2405 linkPart.CreateSelected = true;
2029 2406
2407 lock (m_parts.SyncRoot)
2408 {
2030 //if (linkPart.PhysActor != null) 2409 //if (linkPart.PhysActor != null)
2031 //{ 2410 //{
2032 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2411 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2184,6 +2563,7 @@ namespace OpenSim.Region.Framework.Scenes
2184 /// <param name="objectGroup"></param> 2563 /// <param name="objectGroup"></param>
2185 public virtual void DetachFromBackup() 2564 public virtual void DetachFromBackup()
2186 { 2565 {
2566 m_scene.SceneGraph.FireDetachFromBackup(this);
2187 if (m_isBackedUp && Scene != null) 2567 if (m_isBackedUp && Scene != null)
2188 m_scene.EventManager.OnBackup -= ProcessBackup; 2568 m_scene.EventManager.OnBackup -= ProcessBackup;
2189 2569
@@ -2202,7 +2582,8 @@ namespace OpenSim.Region.Framework.Scenes
2202 2582
2203 axPos *= parentRot; 2583 axPos *= parentRot;
2204 part.OffsetPosition = axPos; 2584 part.OffsetPosition = axPos;
2205 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2585 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2586 part.GroupPosition = newPos;
2206 part.OffsetPosition = Vector3.Zero; 2587 part.OffsetPosition = Vector3.Zero;
2207 part.RotationOffset = worldRot; 2588 part.RotationOffset = worldRot;
2208 2589
@@ -2213,7 +2594,7 @@ namespace OpenSim.Region.Framework.Scenes
2213 2594
2214 part.LinkNum = linkNum; 2595 part.LinkNum = linkNum;
2215 2596
2216 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2597 part.OffsetPosition = newPos - AbsolutePosition;
2217 2598
2218 Quaternion rootRotation = m_rootPart.RotationOffset; 2599 Quaternion rootRotation = m_rootPart.RotationOffset;
2219 2600
@@ -2223,7 +2604,7 @@ namespace OpenSim.Region.Framework.Scenes
2223 2604
2224 parentRot = m_rootPart.RotationOffset; 2605 parentRot = m_rootPart.RotationOffset;
2225 oldRot = part.RotationOffset; 2606 oldRot = part.RotationOffset;
2226 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2607 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2227 part.RotationOffset = newRot; 2608 part.RotationOffset = newRot;
2228 } 2609 }
2229 2610
@@ -2479,8 +2860,12 @@ namespace OpenSim.Region.Framework.Scenes
2479 } 2860 }
2480 } 2861 }
2481 2862
2863 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, SetVolumeDetect);
2482 for (int i = 0; i < parts.Length; i++) 2864 for (int i = 0; i < parts.Length; i++)
2483 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2865 {
2866 if (parts[i] != RootPart)
2867 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, SetVolumeDetect);
2868 }
2484 } 2869 }
2485 } 2870 }
2486 2871
@@ -2493,6 +2878,17 @@ namespace OpenSim.Region.Framework.Scenes
2493 } 2878 }
2494 } 2879 }
2495 2880
2881
2882
2883 /// <summary>
2884 /// Gets the number of parts
2885 /// </summary>
2886 /// <returns></returns>
2887 public int GetPartCount()
2888 {
2889 return Parts.Count();
2890 }
2891
2496 /// <summary> 2892 /// <summary>
2497 /// Update the texture entry for this part 2893 /// Update the texture entry for this part
2498 /// </summary> 2894 /// </summary>
@@ -2549,7 +2945,6 @@ namespace OpenSim.Region.Framework.Scenes
2549 { 2945 {
2550// m_log.DebugFormat( 2946// m_log.DebugFormat(
2551// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 2947// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2552
2553 RootPart.StoreUndoState(true); 2948 RootPart.StoreUndoState(true);
2554 2949
2555 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 2950 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
@@ -2650,7 +3045,6 @@ namespace OpenSim.Region.Framework.Scenes
2650 prevScale.X *= x; 3045 prevScale.X *= x;
2651 prevScale.Y *= y; 3046 prevScale.Y *= y;
2652 prevScale.Z *= z; 3047 prevScale.Z *= z;
2653
2654// RootPart.IgnoreUndoUpdate = true; 3048// RootPart.IgnoreUndoUpdate = true;
2655 RootPart.Resize(prevScale); 3049 RootPart.Resize(prevScale);
2656// RootPart.IgnoreUndoUpdate = false; 3050// RootPart.IgnoreUndoUpdate = false;
@@ -2681,7 +3075,9 @@ namespace OpenSim.Region.Framework.Scenes
2681 } 3075 }
2682 3076
2683// obPart.IgnoreUndoUpdate = false; 3077// obPart.IgnoreUndoUpdate = false;
2684// obPart.StoreUndoState(); 3078 HasGroupChanged = true;
3079 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3080 ScheduleGroupForTerseUpdate();
2685 } 3081 }
2686 3082
2687// m_log.DebugFormat( 3083// m_log.DebugFormat(
@@ -2741,9 +3137,9 @@ namespace OpenSim.Region.Framework.Scenes
2741 { 3137 {
2742 SceneObjectPart part = GetChildPart(localID); 3138 SceneObjectPart part = GetChildPart(localID);
2743 3139
2744// SceneObjectPart[] parts = m_parts.GetArray(); 3140 SceneObjectPart[] parts = m_parts.GetArray();
2745// for (int i = 0; i < parts.Length; i++) 3141 for (int i = 0; i < parts.Length; i++)
2746// parts[i].StoreUndoState(); 3142 parts[i].StoreUndoState();
2747 3143
2748 if (part != null) 3144 if (part != null)
2749 { 3145 {
@@ -2799,10 +3195,27 @@ namespace OpenSim.Region.Framework.Scenes
2799 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3195 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2800 } 3196 }
2801 3197
2802 AbsolutePosition = newPos; 3198 //We have to set undoing here because otherwise an undo state will be saved
3199 if (!m_rootPart.Undoing)
3200 {
3201 m_rootPart.Undoing = true;
3202 AbsolutePosition = newPos;
3203 m_rootPart.Undoing = false;
3204 }
3205 else
3206 {
3207 AbsolutePosition = newPos;
3208 }
2803 3209
2804 HasGroupChanged = true; 3210 HasGroupChanged = true;
2805 ScheduleGroupForTerseUpdate(); 3211 if (m_rootPart.Undoing)
3212 {
3213 ScheduleGroupForFullUpdate();
3214 }
3215 else
3216 {
3217 ScheduleGroupForTerseUpdate();
3218 }
2806 } 3219 }
2807 3220
2808 public void OffsetForNewRegion(Vector3 offset) 3221 public void OffsetForNewRegion(Vector3 offset)
@@ -2884,10 +3297,7 @@ namespace OpenSim.Region.Framework.Scenes
2884 public void UpdateSingleRotation(Quaternion rot, uint localID) 3297 public void UpdateSingleRotation(Quaternion rot, uint localID)
2885 { 3298 {
2886 SceneObjectPart part = GetChildPart(localID); 3299 SceneObjectPart part = GetChildPart(localID);
2887
2888 SceneObjectPart[] parts = m_parts.GetArray(); 3300 SceneObjectPart[] parts = m_parts.GetArray();
2889 for (int i = 0; i < parts.Length; i++)
2890 parts[i].StoreUndoState();
2891 3301
2892 if (part != null) 3302 if (part != null)
2893 { 3303 {
@@ -2925,7 +3335,16 @@ namespace OpenSim.Region.Framework.Scenes
2925 if (part.UUID == m_rootPart.UUID) 3335 if (part.UUID == m_rootPart.UUID)
2926 { 3336 {
2927 UpdateRootRotation(rot); 3337 UpdateRootRotation(rot);
2928 AbsolutePosition = pos; 3338 if (!m_rootPart.Undoing)
3339 {
3340 m_rootPart.Undoing = true;
3341 AbsolutePosition = pos;
3342 m_rootPart.Undoing = false;
3343 }
3344 else
3345 {
3346 AbsolutePosition = pos;
3347 }
2929 } 3348 }
2930 else 3349 else
2931 { 3350 {
@@ -2949,9 +3368,10 @@ namespace OpenSim.Region.Framework.Scenes
2949 3368
2950 Quaternion axRot = rot; 3369 Quaternion axRot = rot;
2951 Quaternion oldParentRot = m_rootPart.RotationOffset; 3370 Quaternion oldParentRot = m_rootPart.RotationOffset;
2952
2953 m_rootPart.StoreUndoState(); 3371 m_rootPart.StoreUndoState();
2954 m_rootPart.UpdateRotation(rot); 3372
3373 //Don't use UpdateRotation because it schedules an update prematurely
3374 m_rootPart.RotationOffset = rot;
2955 if (m_rootPart.PhysActor != null) 3375 if (m_rootPart.PhysActor != null)
2956 { 3376 {
2957 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3377 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2966,14 +3386,14 @@ namespace OpenSim.Region.Framework.Scenes
2966 { 3386 {
2967 prim.IgnoreUndoUpdate = true; 3387 prim.IgnoreUndoUpdate = true;
2968 Vector3 axPos = prim.OffsetPosition; 3388 Vector3 axPos = prim.OffsetPosition;
3389
2969 axPos *= oldParentRot; 3390 axPos *= oldParentRot;
2970 axPos *= Quaternion.Inverse(axRot); 3391 axPos *= Quaternion.Inverse(axRot);
2971 prim.OffsetPosition = axPos; 3392 prim.OffsetPosition = axPos;
2972 Quaternion primsRot = prim.RotationOffset; 3393
2973 Quaternion newRot = primsRot * oldParentRot; 3394 prim.RotationOffset *= Quaternion.Inverse(prim.GetWorldRotation()) * (oldParentRot * prim.RotationOffset);
2974 newRot *= Quaternion.Inverse(axRot); 3395
2975 prim.RotationOffset = newRot; 3396 prim.IgnoreUndoUpdate = false;
2976 prim.ScheduleTerseUpdate();
2977 prim.IgnoreUndoUpdate = false; 3397 prim.IgnoreUndoUpdate = false;
2978 } 3398 }
2979 } 3399 }
@@ -2987,8 +3407,8 @@ namespace OpenSim.Region.Framework.Scenes
2987//// childpart.StoreUndoState(); 3407//// childpart.StoreUndoState();
2988// } 3408// }
2989// } 3409// }
2990 3410 HasGroupChanged = true;
2991 m_rootPart.ScheduleTerseUpdate(); 3411 ScheduleGroupForFullUpdate();
2992 3412
2993// m_log.DebugFormat( 3413// m_log.DebugFormat(
2994// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3414// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
@@ -3216,7 +3636,6 @@ namespace OpenSim.Region.Framework.Scenes
3216 public float GetMass() 3636 public float GetMass()
3217 { 3637 {
3218 float retmass = 0f; 3638 float retmass = 0f;
3219
3220 SceneObjectPart[] parts = m_parts.GetArray(); 3639 SceneObjectPart[] parts = m_parts.GetArray();
3221 for (int i = 0; i < parts.Length; i++) 3640 for (int i = 0; i < parts.Length; i++)
3222 retmass += parts[i].GetMass(); 3641 retmass += parts[i].GetMass();
@@ -3310,6 +3729,14 @@ namespace OpenSim.Region.Framework.Scenes
3310 SetFromItemID(uuid); 3729 SetFromItemID(uuid);
3311 } 3730 }
3312 3731
3732 public void ResetOwnerChangeFlag()
3733 {
3734 ForEachPart(delegate(SceneObjectPart part)
3735 {
3736 part.ResetOwnerChangeFlag();
3737 });
3738 }
3739
3313 #endregion 3740 #endregion
3314 } 3741 }
3315} 3742}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 04fef83..0c3b404 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.OffsetPosition += 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 #region Private Methods 1360 #region Private Methods
@@ -1319,14 +1371,6 @@ namespace OpenSim.Region.Framework.Scenes
1319 } 1371 }
1320 } 1372 }
1321 1373
1322 /// <summary>
1323 /// Clear all pending updates of parts to clients
1324 /// </summary>
1325 private void ClearUpdateSchedule()
1326 {
1327 m_updateFlag = 0;
1328 }
1329
1330 private void SendObjectPropertiesToClient(UUID AgentID) 1374 private void SendObjectPropertiesToClient(UUID AgentID)
1331 { 1375 {
1332 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1376 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1663,6 +1707,9 @@ namespace OpenSim.Region.Framework.Scenes
1663 1707
1664 // Move afterwards ResetIDs as it clears the localID 1708 // Move afterwards ResetIDs as it clears the localID
1665 dupe.LocalId = localID; 1709 dupe.LocalId = localID;
1710 if(dupe.PhysActor != null)
1711 dupe.PhysActor.LocalID = localID;
1712
1666 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1713 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1667 dupe._lastOwnerID = OwnerID; 1714 dupe._lastOwnerID = OwnerID;
1668 1715
@@ -1713,7 +1760,7 @@ namespace OpenSim.Region.Framework.Scenes
1713 PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); 1760 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1714 part.Shape = shape; 1761 part.Shape = shape;
1715 1762
1716 part.Name = "Primitive"; 1763 part.Name = "Object";
1717 part._ownerID = UUID.Random(); 1764 part._ownerID = UUID.Random();
1718 1765
1719 return part; 1766 return part;
@@ -2045,19 +2092,17 @@ namespace OpenSim.Region.Framework.Scenes
2045 public Vector3 GetWorldPosition() 2092 public Vector3 GetWorldPosition()
2046 { 2093 {
2047 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2094 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2048
2049 Vector3 axPos = OffsetPosition; 2095 Vector3 axPos = OffsetPosition;
2050
2051 axPos *= parentRot; 2096 axPos *= parentRot;
2052 Vector3 translationOffsetPosition = axPos; 2097 Vector3 translationOffsetPosition = axPos;
2053 2098 if(_parentID == 0)
2054// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name); 2099 {
2055 2100 return GroupPosition;
2056 Vector3 worldPos = GroupPosition + translationOffsetPosition; 2101 }
2057 2102 else
2058// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name); 2103 {
2059 2104 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2060 return worldPos; 2105 }
2061 } 2106 }
2062 2107
2063 /// <summary> 2108 /// <summary>
@@ -2697,17 +2742,18 @@ namespace OpenSim.Region.Framework.Scenes
2697 //Trys to fetch sound id from prim's inventory. 2742 //Trys to fetch sound id from prim's inventory.
2698 //Prim's inventory doesn't support non script items yet 2743 //Prim's inventory doesn't support non script items yet
2699 2744
2700 lock (TaskInventory) 2745 TaskInventory.LockItemsForRead(true);
2746
2747 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2701 { 2748 {
2702 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2749 if (item.Value.Name == sound)
2703 { 2750 {
2704 if (item.Value.Name == sound) 2751 soundID = item.Value.ItemID;
2705 { 2752 break;
2706 soundID = item.Value.ItemID;
2707 break;
2708 }
2709 } 2753 }
2710 } 2754 }
2755
2756 TaskInventory.LockItemsForRead(false);
2711 } 2757 }
2712 2758
2713 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2759 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2792,7 +2838,7 @@ namespace OpenSim.Region.Framework.Scenes
2792 2838
2793 public void RotLookAt(Quaternion target, float strength, float damping) 2839 public void RotLookAt(Quaternion target, float strength, float damping)
2794 { 2840 {
2795 rotLookAt(target, strength, damping); 2841 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2796 } 2842 }
2797 2843
2798 public void rotLookAt(Quaternion target, float strength, float damping) 2844 public void rotLookAt(Quaternion target, float strength, float damping)
@@ -3033,8 +3079,8 @@ namespace OpenSim.Region.Framework.Scenes
3033 { 3079 {
3034 const float ROTATION_TOLERANCE = 0.01f; 3080 const float ROTATION_TOLERANCE = 0.01f;
3035 const float VELOCITY_TOLERANCE = 0.001f; 3081 const float VELOCITY_TOLERANCE = 0.001f;
3036 const float POSITION_TOLERANCE = 0.05f; 3082 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3037 const int TIME_MS_TOLERANCE = 3000; 3083 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3038 3084
3039 if (m_updateFlag == 1) 3085 if (m_updateFlag == 1)
3040 { 3086 {
@@ -3048,7 +3094,7 @@ namespace OpenSim.Region.Framework.Scenes
3048 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3094 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3049 { 3095 {
3050 AddTerseUpdateToAllAvatars(); 3096 AddTerseUpdateToAllAvatars();
3051 ClearUpdateSchedule(); 3097
3052 3098
3053 // This causes the Scene to 'poll' physical objects every couple of frames 3099 // This causes the Scene to 'poll' physical objects every couple of frames
3054 // bad, so it's been replaced by an event driven method. 3100 // bad, so it's been replaced by an event driven method.
@@ -3066,16 +3112,18 @@ namespace OpenSim.Region.Framework.Scenes
3066 m_lastAngularVelocity = AngularVelocity; 3112 m_lastAngularVelocity = AngularVelocity;
3067 m_lastTerseSent = Environment.TickCount; 3113 m_lastTerseSent = Environment.TickCount;
3068 } 3114 }
3115 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3116 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3069 } 3117 }
3070 else 3118 else
3071 { 3119 {
3072 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3120 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3073 { 3121 {
3074 AddFullUpdateToAllAvatars(); 3122 AddFullUpdateToAllAvatars();
3075 ClearUpdateSchedule(); 3123 m_updateFlag = 0; //Same here
3076 } 3124 }
3077 } 3125 }
3078 ClearUpdateSchedule(); 3126 m_updateFlag = 0;
3079 } 3127 }
3080 3128
3081 /// <summary> 3129 /// <summary>
@@ -3103,17 +3151,16 @@ namespace OpenSim.Region.Framework.Scenes
3103 if (!UUID.TryParse(sound, out soundID)) 3151 if (!UUID.TryParse(sound, out soundID))
3104 { 3152 {
3105 // search sound file from inventory 3153 // search sound file from inventory
3106 lock (TaskInventory) 3154 TaskInventory.LockItemsForRead(true);
3155 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3107 { 3156 {
3108 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3157 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3109 { 3158 {
3110 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3159 soundID = item.Value.ItemID;
3111 { 3160 break;
3112 soundID = item.Value.ItemID;
3113 break;
3114 }
3115 } 3161 }
3116 } 3162 }
3163 TaskInventory.LockItemsForRead(false);
3117 } 3164 }
3118 3165
3119 if (soundID == UUID.Zero) 3166 if (soundID == UUID.Zero)
@@ -3524,7 +3571,7 @@ namespace OpenSim.Region.Framework.Scenes
3524 3571
3525 public void StopLookAt() 3572 public void StopLookAt()
3526 { 3573 {
3527 m_parentGroup.stopLookAt(); 3574 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3528 3575
3529 m_parentGroup.ScheduleGroupForTerseUpdate(); 3576 m_parentGroup.ScheduleGroupForTerseUpdate();
3530 } 3577 }
@@ -3575,45 +3622,45 @@ namespace OpenSim.Region.Framework.Scenes
3575 // TODO: May need to fix for group comparison 3622 // TODO: May need to fix for group comparison
3576 if (last.Compare(this)) 3623 if (last.Compare(this))
3577 { 3624 {
3578 // m_log.DebugFormat( 3625 // m_log.DebugFormat(
3579 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}", 3626 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3580 // Name, LocalId, m_undo.Count); 3627 // Name, LocalId, m_undo.Count);
3581 3628
3582 return; 3629 return;
3583 } 3630 }
3584 } 3631 }
3585 } 3632 }
3586 3633
3587 // m_log.DebugFormat( 3634 // m_log.DebugFormat(
3588 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}", 3635 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3589 // Name, LocalId, forGroup, m_undo.Count); 3636 // Name, LocalId, forGroup, m_undo.Count);
3590 3637
3591 if (m_parentGroup.GetSceneMaxUndo() > 0) 3638 if (m_parentGroup.GetSceneMaxUndo() > 0)
3592 { 3639 {
3593 UndoState nUndo = new UndoState(this, forGroup); 3640 UndoState nUndo = new UndoState(this, forGroup);
3594 3641
3595 m_undo.Push(nUndo); 3642 m_undo.Push(nUndo);
3596 3643
3597 if (m_redo.Count > 0) 3644 if (m_redo.Count > 0)
3598 m_redo.Clear(); 3645 m_redo.Clear();
3599 3646
3600 // m_log.DebugFormat( 3647 // m_log.DebugFormat(
3601 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}", 3648 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3602 // Name, LocalId, forGroup, m_undo.Count); 3649 // Name, LocalId, forGroup, m_undo.Count);
3603 } 3650 }
3604 } 3651 }
3605 } 3652 }
3606 } 3653 }
3607// else 3654 // else
3608// { 3655 // {
3609// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId); 3656 // m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3610// } 3657 // }
3611 } 3658 }
3612// else 3659 // else
3613// { 3660 // {
3614// m_log.DebugFormat( 3661 // m_log.DebugFormat(
3615// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId); 3662 // "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3616// } 3663 // }
3617 } 3664 }
3618 3665
3619 /// <summary> 3666 /// <summary>
@@ -4663,8 +4710,9 @@ namespace OpenSim.Region.Framework.Scenes
4663 { 4710 {
4664 m_shape.TextureEntry = textureEntry; 4711 m_shape.TextureEntry = textureEntry;
4665 TriggerScriptChangedEvent(Changed.TEXTURE); 4712 TriggerScriptChangedEvent(Changed.TEXTURE);
4666 4713 m_updateFlag = 1;
4667 ParentGroup.HasGroupChanged = true; 4714 ParentGroup.HasGroupChanged = true;
4715
4668 //This is madness.. 4716 //This is madness..
4669 //ParentGroup.ScheduleGroupForFullUpdate(); 4717 //ParentGroup.ScheduleGroupForFullUpdate();
4670 //This is sparta 4718 //This is sparta
@@ -4855,5 +4903,17 @@ namespace OpenSim.Region.Framework.Scenes
4855 Color color = Color; 4903 Color color = Color;
4856 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4904 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4857 } 4905 }
4906
4907 public void ResetOwnerChangeFlag()
4908 {
4909 List<UUID> inv = Inventory.GetInventoryList();
4910
4911 foreach (UUID itemID in inv)
4912 {
4913 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4914 item.OwnerChanged = false;
4915 Inventory.UpdateInventoryItem(item, false, false);
4916 }
4917 }
4858 } 4918 }
4859} 4919}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 57adda7..f6b690c 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 159 }
151 foreach (TaskInventoryItem item in items) 160
152 { 161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
153 item.ParentPartID = m_part.UUID; 162 Items.Clear();
154 item.ParentID = m_part.UUID; 163
155 Items.Add(item.ItemID, item); 164 foreach (TaskInventoryItem item in items)
156 } 165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
157 } 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,107 +934,68 @@ 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 if (m_inventoryFileName == String.Empty || 991 if (m_inventoryFileName == String.Empty ||
788 m_inventoryFileNameSerial < m_inventorySerial) 992 m_inventoryFileNameSerial < m_inventorySerial)
789 { 993 {
790 // Something changed, we need to create a new file
791 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 994 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
792 m_inventoryFileNameSerial = m_inventorySerial; 995 m_inventoryFileNameSerial = m_inventorySerial;
793
794 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
795
796 lock (m_items)
797 {
798 foreach (TaskInventoryItem item in m_items.Values)
799 {
800 UUID ownerID = item.OwnerID;
801 uint everyoneMask = 0;
802 uint baseMask = item.BasePermissions;
803 uint ownerMask = item.CurrentPermissions;
804 uint groupMask = item.GroupPermissions;
805
806 invString.AddItemStart();
807 invString.AddNameValueLine("item_id", item.ItemID.ToString());
808 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
809
810 invString.AddPermissionsStart();
811
812 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
813 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
814 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
815 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
816 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
817
818 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
819 invString.AddNameValueLine("owner_id", ownerID.ToString());
820
821 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
822
823 invString.AddNameValueLine("group_id", item.GroupID.ToString());
824 invString.AddSectionEnd();
825
826 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
827 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
828 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
829 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
830
831 invString.AddSaleStart();
832 invString.AddNameValueLine("sale_type", "not");
833 invString.AddNameValueLine("sale_price", "0");
834 invString.AddSectionEnd();
835
836 invString.AddNameValueLine("name", item.Name + "|");
837 invString.AddNameValueLine("desc", item.Description + "|");
838
839 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
840 invString.AddSectionEnd();
841 }
842 }
843
844 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
845
846 return true; 996 return true;
847 } 997 }
848 998
849 // No need to recreate, the existing file is fine
850 return false; 999 return false;
851 } 1000 }
852 1001
@@ -856,26 +1005,99 @@ namespace OpenSim.Region.Framework.Scenes
856 /// <param name="xferManager"></param> 1005 /// <param name="xferManager"></param>
857 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 1006 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
858 { 1007 {
859 CreateInventoryFile(); 1008 bool changed = CreateInventoryFileName();
1009
1010 bool includeAssets = false;
1011 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1012 includeAssets = true;
1013
1014 if (m_inventoryPrivileged != includeAssets)
1015 changed = true;
1016
1017 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1018
1019 Items.LockItemsForRead(true);
860 1020
861 if (m_inventorySerial == 0) // No inventory 1021 if (m_inventorySerial == 0) // No inventory
862 { 1022 {
863 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1023 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1024 Items.LockItemsForRead(false);
864 return; 1025 return;
865 } 1026 }
866 1027
867 // In principle, we should only do the rest if the inventory changed; 1028 if (!changed)
868 // by sending m_inventorySerial to the client, it ought to know 1029 {
869 // that nothing changed and that it doesn't need to request the file. 1030 if (m_inventoryFileData.Length > 2)
870 // Unfortunately, it doesn't look like the client optimizes this; 1031 {
871 // the client seems to always come back and request the Xfer, 1032 xferManager.AddNewFile(m_inventoryFileName,
872 // no matter what value m_inventorySerial has. 1033 m_inventoryFileData);
1034 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1035 Util.StringToBytes256(m_inventoryFileName));
1036
1037 Items.LockItemsForRead(false);
1038 return;
1039 }
1040 }
1041
1042 m_inventoryPrivileged = includeAssets;
1043
1044 foreach (TaskInventoryItem item in m_items.Values)
1045 {
1046 UUID ownerID = item.OwnerID;
1047 uint everyoneMask = 0;
1048 uint baseMask = item.BasePermissions;
1049 uint ownerMask = item.CurrentPermissions;
1050 uint groupMask = item.GroupPermissions;
1051
1052 invString.AddItemStart();
1053 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1054 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1055
1056 invString.AddPermissionsStart();
1057
1058 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1059 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1060 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1061 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1062 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1063
1064 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1065 invString.AddNameValueLine("owner_id", ownerID.ToString());
1066
1067 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1068
1069 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1070 invString.AddSectionEnd();
1071
1072 if (includeAssets)
1073 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1074 else
1075 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1076 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
1077 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
1078 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1079
1080 invString.AddSaleStart();
1081 invString.AddNameValueLine("sale_type", "not");
1082 invString.AddNameValueLine("sale_price", "0");
1083 invString.AddSectionEnd();
1084
1085 invString.AddNameValueLine("name", item.Name + "|");
1086 invString.AddNameValueLine("desc", item.Description + "|");
1087
1088 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1089 invString.AddSectionEnd();
1090 }
1091
1092 Items.LockItemsForRead(false);
1093
1094 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
873 1095
874 if (m_inventoryFileData.Length > 2) 1096 if (m_inventoryFileData.Length > 2)
875 // Add the file for Xfer 1097 {
876 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 1098 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1099 }
877 1100
878 // Tell the client we're ready to Xfer the file
879 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, 1101 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
880 Util.StringToBytes256(m_inventoryFileName)); 1102 Util.StringToBytes256(m_inventoryFileName));
881 } 1103 }
@@ -888,10 +1110,11 @@ namespace OpenSim.Region.Framework.Scenes
888 { 1110 {
889 if (HasInventoryChanged) 1111 if (HasInventoryChanged)
890 { 1112 {
891 HasInventoryChanged = false; 1113 Items.LockItemsForRead(true);
892 List<TaskInventoryItem> items = GetInventoryItems(); 1114 datastore.StorePrimInventory(m_part.UUID, Items.Values);
893 datastore.StorePrimInventory(m_part.UUID, items); 1115 Items.LockItemsForRead(false);
894 1116
1117 HasInventoryChanged = false;
895 } 1118 }
896 } 1119 }
897 1120
@@ -958,82 +1181,63 @@ namespace OpenSim.Region.Framework.Scenes
958 { 1181 {
959 uint mask=0x7fffffff; 1182 uint mask=0x7fffffff;
960 1183
961 lock (m_items) 1184 foreach (TaskInventoryItem item in m_items.Values)
962 { 1185 {
963 foreach (TaskInventoryItem item in m_items.Values) 1186 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1187 mask &= ~((uint)PermissionMask.Copy >> 13);
1188 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1189 mask &= ~((uint)PermissionMask.Transfer >> 13);
1190 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1191 mask &= ~((uint)PermissionMask.Modify >> 13);
1192
1193 if (item.InvType == (int)InventoryType.Object)
964 { 1194 {
965 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1195 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
966 mask &= ~((uint)PermissionMask.Copy >> 13); 1196 mask &= ~((uint)PermissionMask.Copy >> 13);
967 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1197 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
968 mask &= ~((uint)PermissionMask.Transfer >> 13); 1198 mask &= ~((uint)PermissionMask.Transfer >> 13);
969 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1199 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
970 mask &= ~((uint)PermissionMask.Modify >> 13); 1200 mask &= ~((uint)PermissionMask.Modify >> 13);
971
972 if (item.InvType != (int)InventoryType.Object)
973 {
974 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
975 mask &= ~((uint)PermissionMask.Copy >> 13);
976 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
977 mask &= ~((uint)PermissionMask.Transfer >> 13);
978 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
979 mask &= ~((uint)PermissionMask.Modify >> 13);
980 }
981 else
982 {
983 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
984 mask &= ~((uint)PermissionMask.Copy >> 13);
985 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
986 mask &= ~((uint)PermissionMask.Transfer >> 13);
987 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
988 mask &= ~((uint)PermissionMask.Modify >> 13);
989 }
990
991 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
992 mask &= ~(uint)PermissionMask.Copy;
993 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
994 mask &= ~(uint)PermissionMask.Transfer;
995 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
996 mask &= ~(uint)PermissionMask.Modify;
997 } 1201 }
1202
1203 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1204 mask &= ~(uint)PermissionMask.Copy;
1205 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1206 mask &= ~(uint)PermissionMask.Transfer;
1207 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1208 mask &= ~(uint)PermissionMask.Modify;
998 } 1209 }
999
1000 return mask; 1210 return mask;
1001 } 1211 }
1002 1212
1003 public void ApplyNextOwnerPermissions() 1213 public void ApplyNextOwnerPermissions()
1004 { 1214 {
1005 lock (m_items) 1215 foreach (TaskInventoryItem item in m_items.Values)
1006 { 1216 {
1007 foreach (TaskInventoryItem item in m_items.Values) 1217 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1008 { 1218 {
1009 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1219 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1010 { 1220 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1011 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1221 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1012 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1222 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1013 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1223 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1014 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1224 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1015 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1016 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1017 }
1018 item.CurrentPermissions &= item.NextPermissions;
1019 item.BasePermissions &= item.NextPermissions;
1020 item.EveryonePermissions &= item.NextPermissions;
1021 item.OwnerChanged = true;
1022 item.PermsMask = 0;
1023 item.PermsGranter = UUID.Zero;
1024 } 1225 }
1226 item.OwnerChanged = true;
1227 item.CurrentPermissions &= item.NextPermissions;
1228 item.BasePermissions &= item.NextPermissions;
1229 item.EveryonePermissions &= item.NextPermissions;
1230 item.PermsMask = 0;
1231 item.PermsGranter = UUID.Zero;
1025 } 1232 }
1026 } 1233 }
1027 1234
1028 public void ApplyGodPermissions(uint perms) 1235 public void ApplyGodPermissions(uint perms)
1029 { 1236 {
1030 lock (m_items) 1237 foreach (TaskInventoryItem item in m_items.Values)
1031 { 1238 {
1032 foreach (TaskInventoryItem item in m_items.Values) 1239 item.CurrentPermissions = perms;
1033 { 1240 item.BasePermissions = perms;
1034 item.CurrentPermissions = perms;
1035 item.BasePermissions = perms;
1036 }
1037 } 1241 }
1038 1242
1039 m_inventorySerial++; 1243 m_inventorySerial++;
@@ -1046,17 +1250,13 @@ namespace OpenSim.Region.Framework.Scenes
1046 /// <returns></returns> 1250 /// <returns></returns>
1047 public bool ContainsScripts() 1251 public bool ContainsScripts()
1048 { 1252 {
1049 lock (m_items) 1253 foreach (TaskInventoryItem item in m_items.Values)
1050 { 1254 {
1051 foreach (TaskInventoryItem item in m_items.Values) 1255 if (item.InvType == (int)InventoryType.LSL)
1052 { 1256 {
1053 if (item.InvType == (int)InventoryType.LSL) 1257 return true;
1054 {
1055 return true;
1056 }
1057 } 1258 }
1058 } 1259 }
1059
1060 return false; 1260 return false;
1061 } 1261 }
1062 1262
@@ -1064,11 +1264,8 @@ namespace OpenSim.Region.Framework.Scenes
1064 { 1264 {
1065 List<UUID> ret = new List<UUID>(); 1265 List<UUID> ret = new List<UUID>();
1066 1266
1067 lock (m_items) 1267 foreach (TaskInventoryItem item in m_items.Values)
1068 { 1268 ret.Add(item.ItemID);
1069 foreach (TaskInventoryItem item in m_items.Values)
1070 ret.Add(item.ItemID);
1071 }
1072 1269
1073 return ret; 1270 return ret;
1074 } 1271 }
@@ -1099,6 +1296,11 @@ namespace OpenSim.Region.Framework.Scenes
1099 1296
1100 public Dictionary<UUID, string> GetScriptStates() 1297 public Dictionary<UUID, string> GetScriptStates()
1101 { 1298 {
1299 return GetScriptStates(false);
1300 }
1301
1302 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1303 {
1102 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1304 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1103 1305
1104 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1306 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1109,25 +1311,35 @@ namespace OpenSim.Region.Framework.Scenes
1109 if (engines == null) // No engine at all 1311 if (engines == null) // No engine at all
1110 return ret; 1312 return ret;
1111 1313
1112 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1314 Items.LockItemsForRead(true);
1113 1315 foreach (TaskInventoryItem item in m_items.Values)
1114 foreach (TaskInventoryItem item in scripts)
1115 { 1316 {
1116 foreach (IScriptModule e in engines) 1317 if (item.InvType == (int)InventoryType.LSL)
1117 { 1318 {
1118 if (e != null) 1319 foreach (IScriptModule e in engines)
1119 { 1320 {
1120 string n = e.GetXMLState(item.ItemID); 1321 if (e != null)
1121 if (n != String.Empty)
1122 { 1322 {
1123 if (!ret.ContainsKey(item.ItemID)) 1323 string n = e.GetXMLState(item.ItemID);
1124 ret[item.ItemID] = n; 1324 if (n != String.Empty)
1125 break; 1325 {
1326 if (oldIDs)
1327 {
1328 if (!ret.ContainsKey(item.OldItemID))
1329 ret[item.OldItemID] = n;
1330 }
1331 else
1332 {
1333 if (!ret.ContainsKey(item.ItemID))
1334 ret[item.ItemID] = n;
1335 }
1336 break;
1337 }
1126 } 1338 }
1127 } 1339 }
1128 } 1340 }
1129 } 1341 }
1130 1342 Items.LockItemsForRead(false);
1131 return ret; 1343 return ret;
1132 } 1344 }
1133 1345
@@ -1137,21 +1349,27 @@ namespace OpenSim.Region.Framework.Scenes
1137 if (engines == null) 1349 if (engines == null)
1138 return; 1350 return;
1139 1351
1140 List<TaskInventoryItem> scripts = GetInventoryScripts();
1141 1352
1142 foreach (TaskInventoryItem item in scripts) 1353 Items.LockItemsForRead(true);
1354
1355 foreach (TaskInventoryItem item in m_items.Values)
1143 { 1356 {
1144 foreach (IScriptModule engine in engines) 1357 if (item.InvType == (int)InventoryType.LSL)
1145 { 1358 {
1146 if (engine != null) 1359 foreach (IScriptModule engine in engines)
1147 { 1360 {
1148 if (item.OwnerChanged) 1361 if (engine != null)
1149 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1362 {
1150 item.OwnerChanged = false; 1363 if (item.OwnerChanged)
1151 engine.ResumeScript(item.ItemID); 1364 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1365 item.OwnerChanged = false;
1366 engine.ResumeScript(item.ItemID);
1367 }
1152 } 1368 }
1153 } 1369 }
1154 } 1370 }
1371
1372 Items.LockItemsForRead(false);
1155 } 1373 }
1156 } 1374 }
1157} 1375}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a8eff70..7a86f98 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
31using System.Timers; 32using System.Timers;
@@ -72,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes
72// { 73// {
73// m_log.Debug("[ScenePresence] Destructor called"); 74// m_log.Debug("[ScenePresence] Destructor called");
74// } 75// }
75 76
76 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
77 78
78 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
@@ -190,7 +203,8 @@ namespace OpenSim.Region.Framework.Scenes
190 203
191 protected ulong crossingFromRegion; 204 protected ulong crossingFromRegion;
192 205
193 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 206 private readonly Vector3[] Dir_Vectors = new Vector3[11];
207 private bool m_isNudging = false;
194 208
195 // Position of agent's camera in world (region cordinates) 209 // Position of agent's camera in world (region cordinates)
196 protected Vector3 m_CameraCenter; 210 protected Vector3 m_CameraCenter;
@@ -215,17 +229,25 @@ namespace OpenSim.Region.Framework.Scenes
215 private bool m_autopilotMoving; 229 private bool m_autopilotMoving;
216 private Vector3 m_autoPilotTarget; 230 private Vector3 m_autoPilotTarget;
217 private bool m_sitAtAutoTarget; 231 private bool m_sitAtAutoTarget;
232 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
218 233
219 private string m_nextSitAnimation = String.Empty; 234 private string m_nextSitAnimation = String.Empty;
220 235
221 //PauPaw:Proper PID Controler for autopilot************ 236 //PauPaw:Proper PID Controler for autopilot************
222 public bool MovingToTarget { get; private set; } 237 public bool MovingToTarget { get; private set; }
223 public Vector3 MoveToPositionTarget { get; private set; } 238 public Vector3 MoveToPositionTarget { get; private set; }
239 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
224 240
225 private bool m_followCamAuto; 241 private bool m_followCamAuto;
226 242
227 private int m_movementUpdateCount; 243 private int m_movementUpdateCount;
244 private int m_lastColCount = -1; //KF: Look for Collision chnages
245 private int m_updateCount = 0; //KF: Update Anims for a while
246 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
228 private const int NumMovementsBetweenRayCast = 5; 247 private const int NumMovementsBetweenRayCast = 5;
248 private List<uint> m_lastColliders = new List<uint>();
249
250 private object m_syncRoot = new Object();
229 251
230 private bool CameraConstraintActive; 252 private bool CameraConstraintActive;
231 //private int m_moveToPositionStateStatus; 253 //private int m_moveToPositionStateStatus;
@@ -262,7 +284,9 @@ namespace OpenSim.Region.Framework.Scenes
262 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 284 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
263 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 285 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
264 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 286 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
265 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 287 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
288 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
289 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
266 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 290 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
267 } 291 }
268 292
@@ -466,7 +490,8 @@ namespace OpenSim.Region.Framework.Scenes
466 get 490 get
467 { 491 {
468 PhysicsActor actor = m_physicsActor; 492 PhysicsActor actor = m_physicsActor;
469 if (actor != null) 493// if (actor != null)
494 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
470 m_pos = actor.Position; 495 m_pos = actor.Position;
471 else 496 else
472 { 497 {
@@ -488,7 +513,7 @@ namespace OpenSim.Region.Framework.Scenes
488 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 513 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
489 if (part != null) 514 if (part != null)
490 { 515 {
491 return m_parentPosition + (m_pos * part.GetWorldRotation()); 516 return part.AbsolutePosition + (m_pos * part.GetWorldRotation());
492 } 517 }
493 else 518 else
494 { 519 {
@@ -515,7 +540,8 @@ namespace OpenSim.Region.Framework.Scenes
515 } 540 }
516 } 541 }
517 542
518 m_pos = value; 543 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
544 m_pos = value;
519 m_parentPosition = Vector3.Zero; 545 m_parentPosition = Vector3.Zero;
520 } 546 }
521 } 547 }
@@ -559,10 +585,39 @@ namespace OpenSim.Region.Framework.Scenes
559 } 585 }
560 } 586 }
561 587
588 public Quaternion OffsetRotation
589 {
590 get { return m_offsetRotation; }
591 set { m_offsetRotation = value; }
592 }
593
562 public Quaternion Rotation 594 public Quaternion Rotation
563 { 595 {
564 get { return m_bodyRot; } 596 get {
565 set { m_bodyRot = value; } 597 if (m_parentID != 0)
598 {
599 if (m_offsetRotation != null)
600 {
601 return m_offsetRotation;
602 }
603 else
604 {
605 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
606 }
607
608 }
609 else
610 {
611 return m_bodyRot;
612 }
613 }
614 set {
615 m_bodyRot = value;
616 if (m_parentID != 0)
617 {
618 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
619 }
620 }
566 } 621 }
567 622
568 public Quaternion PreviousRotation 623 public Quaternion PreviousRotation
@@ -587,11 +642,21 @@ namespace OpenSim.Region.Framework.Scenes
587 642
588 private uint m_parentID; 643 private uint m_parentID;
589 644
645
646 private UUID m_linkedPrim;
647
590 public uint ParentID 648 public uint ParentID
591 { 649 {
592 get { return m_parentID; } 650 get { return m_parentID; }
593 set { m_parentID = value; } 651 set { m_parentID = value; }
594 } 652 }
653
654 public UUID LinkedPrim
655 {
656 get { return m_linkedPrim; }
657 set { m_linkedPrim = value; }
658 }
659
595 public float Health 660 public float Health
596 { 661 {
597 get { return m_health; } 662 get { return m_health; }
@@ -727,6 +792,7 @@ namespace OpenSim.Region.Framework.Scenes
727 m_localId = m_scene.AllocateLocalId(); 792 m_localId = m_scene.AllocateLocalId();
728 793
729 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 794 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
795 m_userFlags = account.UserFlags;
730 796
731 if (account != null) 797 if (account != null)
732 m_userLevel = account.UserLevel; 798 m_userLevel = account.UserLevel;
@@ -745,10 +811,7 @@ namespace OpenSim.Region.Framework.Scenes
745 m_reprioritization_timer.AutoReset = false; 811 m_reprioritization_timer.AutoReset = false;
746 812
747 AdjustKnownSeeds(); 813 AdjustKnownSeeds();
748
749 // TODO: I think, this won't send anything, as we are still a child here...
750 Animator.TrySetMovementAnimation("STAND"); 814 Animator.TrySetMovementAnimation("STAND");
751
752 // we created a new ScenePresence (a new child agent) in a fresh region. 815 // we created a new ScenePresence (a new child agent) in a fresh region.
753 // Request info about all the (root) agents in this region 816 // Request info about all the (root) agents in this region
754 // Note: This won't send data *to* other clients in that region (children don't send) 817 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -789,25 +852,47 @@ namespace OpenSim.Region.Framework.Scenes
789 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 852 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
790 Dir_Vectors[4] = Vector3.UnitZ; //UP 853 Dir_Vectors[4] = Vector3.UnitZ; //UP
791 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 854 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
792 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 855 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
793 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 856 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
794 Dir_Vectors[7] = -Vector3.UnitX; //BACK 857 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
858 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
859 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
795 } 860 }
796 861
797 private Vector3[] GetWalkDirectionVectors() 862 private Vector3[] GetWalkDirectionVectors()
798 { 863 {
799 Vector3[] vector = new Vector3[9]; 864 Vector3[] vector = new Vector3[11];
800 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 865 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
801 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 866 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
802 vector[2] = Vector3.UnitY; //LEFT 867 vector[2] = Vector3.UnitY; //LEFT
803 vector[3] = -Vector3.UnitY; //RIGHT 868 vector[3] = -Vector3.UnitY; //RIGHT
804 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 869 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
805 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 870 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
806 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 871 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
807 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 872 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
808 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 873 vector[8] = Vector3.UnitY; //LEFT_NUDGE
874 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
875 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
809 return vector; 876 return vector;
810 } 877 }
878
879 private bool[] GetDirectionIsNudge()
880 {
881 bool[] isNudge = new bool[11];
882 isNudge[0] = false; //FORWARD
883 isNudge[1] = false; //BACK
884 isNudge[2] = false; //LEFT
885 isNudge[3] = false; //RIGHT
886 isNudge[4] = false; //UP
887 isNudge[5] = false; //DOWN
888 isNudge[6] = true; //FORWARD_NUDGE
889 isNudge[7] = true; //BACK_NUDGE
890 isNudge[8] = true; //LEFT_NUDGE
891 isNudge[9] = true; //RIGHT_NUDGE
892 isNudge[10] = true; //DOWN_Nudge
893 return isNudge;
894 }
895
811 896
812 #endregion 897 #endregion
813 898
@@ -872,6 +957,62 @@ namespace OpenSim.Region.Framework.Scenes
872 pos.Y = crossedBorder.BorderLine.Z - 1; 957 pos.Y = crossedBorder.BorderLine.Z - 1;
873 } 958 }
874 959
960 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
961 if (land != null)
962 {
963 // If we come in via login, landmark or map, we want to
964 // honor landing points. If we come in via Lure, we want
965 // to ignore them.
966 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
967 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ||
968 (m_teleportFlags & TeleportFlags.ViaLocation) != 0)
969 {
970 // Don't restrict gods, estate managers, or land owners to
971 // the TP point. This behaviour mimics agni.
972 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
973 land.LandData.UserLocation != Vector3.Zero &&
974 GodLevel < 200 &&
975 ((land.LandData.OwnerID != m_uuid &&
976 (!m_scene.Permissions.IsGod(m_uuid)) &&
977 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0))
978 {
979 pos = land.LandData.UserLocation;
980 }
981 }
982
983 land.SendLandUpdateToClient(ControllingClient);
984 }
985
986 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
987 {
988 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
989
990 if (pos.X < 0)
991 {
992 emergencyPos.X = (int)Constants.RegionSize + pos.X;
993 if (!(pos.Y < 0))
994 emergencyPos.Y = pos.Y;
995 if (!(pos.Z < 0))
996 emergencyPos.Z = pos.Z;
997 }
998 if (pos.Y < 0)
999 {
1000 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
1001 if (!(pos.X < 0))
1002 emergencyPos.X = pos.X;
1003 if (!(pos.Z < 0))
1004 emergencyPos.Z = pos.Z;
1005 }
1006 if (pos.Z < 0)
1007 {
1008 emergencyPos.Z = 128;
1009 if (!(pos.Y < 0))
1010 emergencyPos.Y = pos.Y;
1011 if (!(pos.X < 0))
1012 emergencyPos.X = pos.X;
1013 }
1014 }
1015
875 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1016 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
876 { 1017 {
877 m_log.WarnFormat( 1018 m_log.WarnFormat(
@@ -1004,16 +1145,21 @@ namespace OpenSim.Region.Framework.Scenes
1004 /// <summary> 1145 /// <summary>
1005 /// Removes physics plugin scene representation of this agent if it exists. 1146 /// Removes physics plugin scene representation of this agent if it exists.
1006 /// </summary> 1147 /// </summary>
1007 private void RemoveFromPhysicalScene() 1148 public void RemoveFromPhysicalScene()
1008 { 1149 {
1009 if (PhysicsActor != null) 1150 if (PhysicsActor != null)
1010 { 1151 {
1011 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1152 try
1012 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1153 {
1013 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1154 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1014 m_physicsActor.UnSubscribeEvents(); 1155 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
1015 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1156 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1016 PhysicsActor = null; 1157 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1158 m_physicsActor.UnSubscribeEvents();
1159 PhysicsActor = null;
1160 }
1161 catch
1162 { }
1017 } 1163 }
1018 } 1164 }
1019 1165
@@ -1024,15 +1170,18 @@ namespace OpenSim.Region.Framework.Scenes
1024 public void Teleport(Vector3 pos) 1170 public void Teleport(Vector3 pos)
1025 { 1171 {
1026 bool isFlying = false; 1172 bool isFlying = false;
1173
1027 if (m_physicsActor != null) 1174 if (m_physicsActor != null)
1028 isFlying = m_physicsActor.Flying; 1175 isFlying = m_physicsActor.Flying;
1029 1176
1030 RemoveFromPhysicalScene(); 1177 RemoveFromPhysicalScene();
1031 Velocity = Vector3.Zero; 1178 Velocity = Vector3.Zero;
1179 CheckLandingPoint(ref pos);
1032 AbsolutePosition = pos; 1180 AbsolutePosition = pos;
1033 AddToPhysicalScene(isFlying); 1181 AddToPhysicalScene(isFlying);
1034 1182
1035 SendTerseUpdateToAllClients(); 1183 SendTerseUpdateToAllClients();
1184
1036 } 1185 }
1037 1186
1038 public void TeleportWithMomentum(Vector3 pos) 1187 public void TeleportWithMomentum(Vector3 pos)
@@ -1042,6 +1191,7 @@ namespace OpenSim.Region.Framework.Scenes
1042 isFlying = m_physicsActor.Flying; 1191 isFlying = m_physicsActor.Flying;
1043 1192
1044 RemoveFromPhysicalScene(); 1193 RemoveFromPhysicalScene();
1194 CheckLandingPoint(ref pos);
1045 AbsolutePosition = pos; 1195 AbsolutePosition = pos;
1046 AddToPhysicalScene(isFlying); 1196 AddToPhysicalScene(isFlying);
1047 1197
@@ -1217,9 +1367,12 @@ namespace OpenSim.Region.Framework.Scenes
1217 /// <summary> 1367 /// <summary>
1218 /// This is the event handler for client movement. If a client is moving, this event is triggering. 1368 /// This is the event handler for client movement. If a client is moving, this event is triggering.
1219 /// </summary> 1369 /// </summary>
1370 /// <summary>
1371 /// This is the event handler for client movement. If a client is moving, this event is triggering.
1372 /// </summary>
1220 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 1373 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1221 { 1374 {
1222// m_log.DebugFormat("[SCENE PRESENCE]: Received agent update from {0}", remoteClient.Name); 1375 // m_log.DebugFormat("[SCENE PRESENCE]: Received agent update from {0}", remoteClient.Name);
1223 1376
1224 //if (m_isChildAgent) 1377 //if (m_isChildAgent)
1225 //{ 1378 //{
@@ -1415,12 +1568,12 @@ namespace OpenSim.Region.Framework.Scenes
1415 1568
1416 if ((m_movementflag & (byte)(uint)DCF) == 0) 1569 if ((m_movementflag & (byte)(uint)DCF) == 0)
1417 { 1570 {
1418 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) 1571 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACK_NUDGE)
1419 { 1572 {
1420 m_movementflag |= (byte)nudgehack; 1573 m_movementflag |= (byte)nudgehack;
1421 } 1574 }
1422 1575
1423// m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with {1}", Name, DCF); 1576 // m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with {1}", Name, DCF);
1424 m_movementflag += (byte)(uint)DCF; 1577 m_movementflag += (byte)(uint)DCF;
1425 update_movementflag = true; 1578 update_movementflag = true;
1426 } 1579 }
@@ -1428,11 +1581,11 @@ namespace OpenSim.Region.Framework.Scenes
1428 else 1581 else
1429 { 1582 {
1430 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1583 if ((m_movementflag & (byte)(uint)DCF) != 0 ||
1431 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE) 1584 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACK_NUDGE)
1432 && ((m_movementflag & (byte)nudgehack) == nudgehack)) 1585 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1433 ) // This or is for Nudge forward 1586 ) // This or is for Nudge forward
1434 { 1587 {
1435// m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with lack of {1}", Name, DCF); 1588 // m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with lack of {1}", Name, DCF);
1436 m_movementflag -= ((byte)(uint)DCF); 1589 m_movementflag -= ((byte)(uint)DCF);
1437 update_movementflag = true; 1590 update_movementflag = true;
1438 1591
@@ -1497,21 +1650,21 @@ namespace OpenSim.Region.Framework.Scenes
1497 // which occurs later in the main scene loop 1650 // which occurs later in the main scene loop
1498 if (update_movementflag || (update_rotation && DCFlagKeyPressed)) 1651 if (update_movementflag || (update_rotation && DCFlagKeyPressed))
1499 { 1652 {
1500// m_log.DebugFormat( 1653 // m_log.DebugFormat(
1501// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", 1654 // "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}",
1502// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); 1655 // m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation);
1503 1656
1504 AddNewMovement(agent_control_v3); 1657 AddNewMovement(agent_control_v3);
1505 } 1658 }
1506// else 1659 // else
1507// { 1660 // {
1508// if (!update_movementflag) 1661 // if (!update_movementflag)
1509// { 1662 // {
1510// m_log.DebugFormat( 1663 // m_log.DebugFormat(
1511// "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false", 1664 // "[SCENE PRESENCE]: In {0} ignoring requested update of {1} for {2} as update_movementflag = false",
1512// m_scene.RegionInfo.RegionName, agent_control_v3, Name); 1665 // m_scene.RegionInfo.RegionName, agent_control_v3, Name);
1513// } 1666 // }
1514// } 1667 // }
1515 1668
1516 if (update_movementflag && m_parentID == 0) 1669 if (update_movementflag && m_parentID == 0)
1517 Animator.UpdateMovementAnimations(); 1670 Animator.UpdateMovementAnimations();
@@ -1532,20 +1685,20 @@ namespace OpenSim.Region.Framework.Scenes
1532 /// <returns>True if movement has been updated in some way. False otherwise.</returns> 1685 /// <returns>True if movement has been updated in some way. False otherwise.</returns>
1533 public bool HandleMoveToTargetUpdate(ref Vector3 agent_control_v3) 1686 public bool HandleMoveToTargetUpdate(ref Vector3 agent_control_v3)
1534 { 1687 {
1535// m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name); 1688 // m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name);
1536 1689
1537 bool updated = false; 1690 bool updated = false;
1538 1691
1539// m_log.DebugFormat( 1692 // m_log.DebugFormat(
1540// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", 1693 // "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}",
1541// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); 1694 // allowUpdate, m_moveToPositionInProgress, m_autopilotMoving);
1542 1695
1543 if (!m_autopilotMoving) 1696 if (!m_autopilotMoving)
1544 { 1697 {
1545 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); 1698 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget);
1546// m_log.DebugFormat( 1699 // m_log.DebugFormat(
1547// "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}", 1700 // "[SCENE PRESENCE]: Abs pos of {0} is {1}, target {2}, distance {3}",
1548// Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget); 1701 // Name, AbsolutePosition, MoveToPositionTarget, distanceToTarget);
1549 1702
1550 // Check the error term of the current position in relation to the target position 1703 // Check the error term of the current position in relation to the target position
1551 if (distanceToTarget <= 1) 1704 if (distanceToTarget <= 1)
@@ -1568,7 +1721,7 @@ namespace OpenSim.Region.Framework.Scenes
1568 (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 1721 (MoveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
1569 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords 1722 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(Rotation)); // change to avatar coords
1570 // Ignore z component of vector 1723 // Ignore z component of vector
1571// Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1724 // Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1572 LocalVectorToTarget3D.Normalize(); 1725 LocalVectorToTarget3D.Normalize();
1573 1726
1574 // update avatar movement flags. the avatar coordinate system is as follows: 1727 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1634,9 +1787,9 @@ namespace OpenSim.Region.Framework.Scenes
1634 updated = true; 1787 updated = true;
1635 } 1788 }
1636 1789
1637// m_log.DebugFormat( 1790 // m_log.DebugFormat(
1638// "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}", 1791 // "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}",
1639// LocalVectorToTarget3D, agent_control_v3, Name); 1792 // LocalVectorToTarget3D, agent_control_v3, Name);
1640 1793
1641 agent_control_v3 += LocalVectorToTarget3D; 1794 agent_control_v3 += LocalVectorToTarget3D;
1642 } 1795 }
@@ -1738,7 +1891,7 @@ namespace OpenSim.Region.Framework.Scenes
1738 Velocity = Vector3.Zero; 1891 Velocity = Vector3.Zero;
1739 SendAvatarDataToAllAgents(); 1892 SendAvatarDataToAllAgents();
1740 1893
1741 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1894 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1742 } 1895 }
1743 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1896 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1744 m_requestedSitTargetUUID = UUID.Zero; 1897 m_requestedSitTargetUUID = UUID.Zero;
@@ -1775,25 +1928,22 @@ namespace OpenSim.Region.Framework.Scenes
1775 1928
1776 if (m_parentID != 0) 1929 if (m_parentID != 0)
1777 { 1930 {
1778 m_log.Debug("StandupCode Executed"); 1931 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1779 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1780 if (part != null) 1932 if (part != null)
1781 { 1933 {
1934 part.TaskInventory.LockItemsForRead(true);
1782 TaskInventoryDictionary taskIDict = part.TaskInventory; 1935 TaskInventoryDictionary taskIDict = part.TaskInventory;
1783 if (taskIDict != null) 1936 if (taskIDict != null)
1784 { 1937 {
1785 lock (taskIDict) 1938 foreach (UUID taskID in taskIDict.Keys)
1786 { 1939 {
1787 foreach (UUID taskID in taskIDict.Keys) 1940 UnRegisterControlEventsToScript(LocalId, taskID);
1788 { 1941 taskIDict[taskID].PermsMask &= ~(
1789 UnRegisterControlEventsToScript(LocalId, taskID); 1942 2048 | //PERMISSION_CONTROL_CAMERA
1790 taskIDict[taskID].PermsMask &= ~( 1943 4); // PERMISSION_TAKE_CONTROLS
1791 2048 | //PERMISSION_CONTROL_CAMERA
1792 4); // PERMISSION_TAKE_CONTROLS
1793 }
1794 } 1944 }
1795
1796 } 1945 }
1946 part.TaskInventory.LockItemsForRead(false);
1797 // Reset sit target. 1947 // Reset sit target.
1798 if (part.GetAvatarOnSitTarget() == UUID) 1948 if (part.GetAvatarOnSitTarget() == UUID)
1799 part.SitTargetAvatar = UUID.Zero; 1949 part.SitTargetAvatar = UUID.Zero;
@@ -1802,20 +1952,58 @@ namespace OpenSim.Region.Framework.Scenes
1802 m_parentPosition = part.GetWorldPosition(); 1952 m_parentPosition = part.GetWorldPosition();
1803 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1953 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1804 } 1954 }
1955 // part.GetWorldRotation() is the rotation of the object being sat on
1956 // Rotation is the sittiing Av's rotation
1957
1958 Quaternion partRot;
1959// if (part.LinkNum == 1)
1960// { // Root prim of linkset
1961// partRot = part.ParentGroup.RootPart.RotationOffset;
1962// }
1963// else
1964// { // single or child prim
1965
1966// }
1967 if (part == null) //CW: Part may be gone. llDie() for example.
1968 {
1969 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1970 }
1971 else
1972 {
1973 partRot = part.GetWorldRotation();
1974 }
1975
1976 Quaternion partIRot = Quaternion.Inverse(partRot);
1805 1977
1978 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1979 Vector3 avStandUp = new Vector3(0.3f, 0f, 0f) * avatarRot; // 0.3M infront of av
1980
1981
1806 if (m_physicsActor == null) 1982 if (m_physicsActor == null)
1807 { 1983 {
1808 AddToPhysicalScene(false); 1984 AddToPhysicalScene(false);
1809 } 1985 }
1810 1986 //CW: If the part isn't null then we can set the current position
1811 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1987 if (part != null)
1812 m_parentPosition = Vector3.Zero; 1988 {
1813 1989 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1814 m_parentID = 0; 1990 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1991 part.IsOccupied = false;
1992 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1993 }
1994 else
1995 {
1996 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1997 AbsolutePosition = m_lastWorldPosition;
1998 }
1999
2000 m_parentPosition = Vector3.Zero;
2001 m_parentID = 0;
2002 m_linkedPrim = UUID.Zero;
2003 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1815 SendAvatarDataToAllAgents(); 2004 SendAvatarDataToAllAgents();
1816 m_requestedSitTargetID = 0; 2005 m_requestedSitTargetID = 0;
1817 } 2006 }
1818
1819 Animator.TrySetMovementAnimation("STAND"); 2007 Animator.TrySetMovementAnimation("STAND");
1820 } 2008 }
1821 2009
@@ -1846,13 +2034,9 @@ namespace OpenSim.Region.Framework.Scenes
1846 Vector3 avSitOffSet = part.SitTargetPosition; 2034 Vector3 avSitOffSet = part.SitTargetPosition;
1847 Quaternion avSitOrientation = part.SitTargetOrientation; 2035 Quaternion avSitOrientation = part.SitTargetOrientation;
1848 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2036 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1849 2037 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1850 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2038 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1851 bool SitTargetisSet = 2039 if (SitTargetisSet && !SitTargetOccupied)
1852 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1853 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1854
1855 if (SitTargetisSet && SitTargetUnOccupied)
1856 { 2040 {
1857 //switch the target to this prim 2041 //switch the target to this prim
1858 return part; 2042 return part;
@@ -1866,85 +2050,168 @@ namespace OpenSim.Region.Framework.Scenes
1866 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 2050 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1867 { 2051 {
1868 bool autopilot = true; 2052 bool autopilot = true;
2053 Vector3 autopilotTarget = new Vector3();
2054 Quaternion sitOrientation = Quaternion.Identity;
1869 Vector3 pos = new Vector3(); 2055 Vector3 pos = new Vector3();
1870 Quaternion sitOrientation = pSitOrientation;
1871 Vector3 cameraEyeOffset = Vector3.Zero; 2056 Vector3 cameraEyeOffset = Vector3.Zero;
1872 Vector3 cameraAtOffset = Vector3.Zero; 2057 Vector3 cameraAtOffset = Vector3.Zero;
1873 bool forceMouselook = false; 2058 bool forceMouselook = false;
1874 2059
1875 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 2060 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1876 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 2061 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1877 if (part != null) 2062 if (part == null) return;
2063
2064 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
2065 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
2066
2067 // part is the prim to sit on
2068 // offset is the world-ref vector distance from that prim center to the click-spot
2069 // UUID is the UUID of the Avatar doing the clicking
2070
2071 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
2072
2073 // Is a sit target available?
2074 Vector3 avSitOffSet = part.SitTargetPosition;
2075 Quaternion avSitOrientation = part.SitTargetOrientation;
2076
2077 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
2078 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
2079 Quaternion partRot;
2080// if (part.LinkNum == 1)
2081// { // Root prim of linkset
2082// partRot = part.ParentGroup.RootPart.RotationOffset;
2083// }
2084// else
2085// { // single or child prim
2086 partRot = part.GetWorldRotation();
2087// }
2088 Quaternion partIRot = Quaternion.Inverse(partRot);
2089//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
2090 // Sit analysis rewritten by KF 091125
2091 if (SitTargetisSet) // scipted sit
1878 { 2092 {
1879 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 2093 if (!part.IsOccupied)
1880 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 2094 {
1881 2095//Console.WriteLine("Scripted, unoccupied");
1882 // Is a sit target available? 2096 part.SitTargetAvatar = UUID; // set that Av will be on it
1883 Vector3 avSitOffSet = part.SitTargetPosition; 2097 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1884 Quaternion avSitOrientation = part.SitTargetOrientation; 2098
1885 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2099 Quaternion nrot = avSitOrientation;
1886 2100 if (!part.IsRoot)
1887 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
1888 bool SitTargetisSet =
1889 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f &&
1890 (
1891 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion
1892 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point
1893 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion
1894 )
1895 ));
1896
1897 if (SitTargetisSet && SitTargetUnOccupied)
1898 {
1899 part.SitTargetAvatar = UUID;
1900 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z);
1901 sitOrientation = avSitOrientation;
1902 autopilot = false;
1903 }
1904 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1905
1906 pos = part.AbsolutePosition + offset;
1907 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1)
1908 //{
1909 // offset = pos;
1910 //autopilot = false;
1911 //}
1912 if (m_physicsActor != null)
1913 {
1914 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1915 // We can remove the physicsActor until they stand up.
1916 m_sitAvatarHeight = m_physicsActor.Size.Z;
1917
1918 if (autopilot)
1919 { 2101 {
1920 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 2102 nrot = part.RotationOffset * avSitOrientation;
1921 {
1922 autopilot = false;
1923
1924 RemoveFromPhysicalScene();
1925 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1926 }
1927 } 2103 }
1928 else 2104 sitOrientation = nrot; // Change rotatione to the scripted one
2105 OffsetRotation = nrot;
2106 autopilot = false; // Jump direct to scripted llSitPos()
2107 }
2108 else
2109 {
2110//Console.WriteLine("Scripted, occupied");
2111 return;
2112 }
2113 }
2114 else // Not Scripted
2115 {
2116 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
2117 {
2118 // large prim & offset, ignore if other Avs sitting
2119// offset.Z -= 0.05f;
2120 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
2121 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
2122
2123//Console.WriteLine(" offset ={0}", offset);
2124//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
2125//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
2126
2127 }
2128 else // small offset
2129 {
2130//Console.WriteLine("Small offset");
2131 if (!part.IsOccupied)
2132 {
2133 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2134 autopilotTarget = part.AbsolutePosition;
2135//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2136 }
2137 else return; // occupied small
2138 } // end large/small
2139 } // end Scripted/not
2140
2141 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2142
2143 cameraAtOffset = part.GetCameraAtOffset();
2144 cameraEyeOffset = part.GetCameraEyeOffset();
2145 forceMouselook = part.GetForceMouselook();
2146 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2147 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2148
2149 if (m_physicsActor != null)
2150 {
2151 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2152 // We can remove the physicsActor until they stand up.
2153 m_sitAvatarHeight = m_physicsActor.Size.Z;
2154 if (autopilot)
2155 { // its not a scripted sit
2156// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2157 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1929 { 2158 {
2159 autopilot = false; // close enough
2160 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2161 Not using the part's position because returning the AV to the last known standing
2162 position is likely to be more friendly, isn't it? */
1930 RemoveFromPhysicalScene(); 2163 RemoveFromPhysicalScene();
1931 } 2164 Velocity = Vector3.Zero;
2165 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2166 } // else the autopilot will get us close
2167 }
2168 else
2169 { // its a scripted sit
2170 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2171 I *am* using the part's position this time because we have no real idea how far away
2172 the avatar is from the sit target. */
2173 RemoveFromPhysicalScene();
2174 Velocity = Vector3.Zero;
1932 } 2175 }
1933
1934 cameraAtOffset = part.GetCameraAtOffset();
1935 cameraEyeOffset = part.GetCameraEyeOffset();
1936 forceMouselook = part.GetForceMouselook();
1937 } 2176 }
1938 2177 else return; // physactor is null!
1939 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2178
1940 m_requestedSitTargetUUID = targetID; 2179 Vector3 offsetr; // = offset * partIRot;
2180 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2181 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2182 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2183 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2184 //offsetr = offset * partIRot;
2185//
2186 // }
2187 // else
2188 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2189 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2190 // (offset * partRot);
2191 // }
2192
2193//Console.WriteLine(" ");
2194//Console.WriteLine("link number ={0}", part.LinkNum);
2195//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2196//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2197//Console.WriteLine("Click offst ={0}", offset);
2198//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2199//Console.WriteLine("offsetr ={0}", offsetr);
2200//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2201//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2202
2203 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2204 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2205
2206 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1941 // This calls HandleAgentSit twice, once from here, and the client calls 2207 // This calls HandleAgentSit twice, once from here, and the client calls
1942 // HandleAgentSit itself after it gets to the location 2208 // HandleAgentSit itself after it gets to the location
1943 // It doesn't get to the location until we've moved them there though 2209 // It doesn't get to the location until we've moved them there though
1944 // which happens in HandleAgentSit :P 2210 // which happens in HandleAgentSit :P
1945 m_autopilotMoving = autopilot; 2211 m_autopilotMoving = autopilot;
1946 m_autoPilotTarget = pos; 2212 m_autoPilotTarget = autopilotTarget;
1947 m_sitAtAutoTarget = autopilot; 2213 m_sitAtAutoTarget = autopilot;
2214 m_initialSitTarget = autopilotTarget;
1948 if (!autopilot) 2215 if (!autopilot)
1949 HandleAgentSit(remoteClient, UUID); 2216 HandleAgentSit(remoteClient, UUID);
1950 } 2217 }
@@ -2209,47 +2476,130 @@ namespace OpenSim.Region.Framework.Scenes
2209 { 2476 {
2210 if (part != null) 2477 if (part != null)
2211 { 2478 {
2479//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2212 if (part.GetAvatarOnSitTarget() == UUID) 2480 if (part.GetAvatarOnSitTarget() == UUID)
2213 { 2481 {
2482//Console.WriteLine("Scripted Sit");
2483 // Scripted sit
2214 Vector3 sitTargetPos = part.SitTargetPosition; 2484 Vector3 sitTargetPos = part.SitTargetPosition;
2215 Quaternion sitTargetOrient = part.SitTargetOrientation; 2485 Quaternion sitTargetOrient = part.SitTargetOrientation;
2216
2217 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2218 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2219
2220 //Quaternion result = (sitTargetOrient * vq) * nq;
2221
2222 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2486 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2223 m_pos += SIT_TARGET_ADJUSTMENT; 2487 m_pos += SIT_TARGET_ADJUSTMENT;
2488 if (!part.IsRoot)
2489 {
2490 m_pos *= part.RotationOffset;
2491 }
2224 m_bodyRot = sitTargetOrient; 2492 m_bodyRot = sitTargetOrient;
2225 //Rotation = sitTargetOrient;
2226 m_parentPosition = part.AbsolutePosition; 2493 m_parentPosition = part.AbsolutePosition;
2227 2494 part.IsOccupied = true;
2228 //SendTerseUpdateToAllClients(); 2495 part.ParentGroup.AddAvatar(agentID);
2229 } 2496 }
2230 else 2497 else
2231 { 2498 {
2232 m_pos -= part.AbsolutePosition; 2499 // if m_avUnscriptedSitPos is zero then Av sits above center
2500 // Else Av sits at m_avUnscriptedSitPos
2501
2502 // Non-scripted sit by Kitto Flora 21Nov09
2503 // Calculate angle of line from prim to Av
2504 Quaternion partIRot;
2505// if (part.LinkNum == 1)
2506// { // Root prim of linkset
2507// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2508// }
2509// else
2510// { // single or child prim
2511 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2512// }
2513 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2514 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2515 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2516 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2517 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2518 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2519 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2520 // Av sits at world euler <0,0, z>, translated by part rotation
2521 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2522
2233 m_parentPosition = part.AbsolutePosition; 2523 m_parentPosition = part.AbsolutePosition;
2234 } 2524 part.IsOccupied = true;
2525 part.ParentGroup.AddAvatar(agentID);
2526 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2527 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2528 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2529 m_avUnscriptedSitPos; // adds click offset, if any
2530 //Set up raytrace to find top surface of prim
2531 Vector3 size = part.Scale;
2532 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2533 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2534 Vector3 down = new Vector3(0f, 0f, -1f);
2535//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2536 m_scene.PhysicsScene.RaycastWorld(
2537 start, // Vector3 position,
2538 down, // Vector3 direction,
2539 mag, // float length,
2540 SitAltitudeCallback); // retMethod
2541 } // end scripted/not
2235 } 2542 }
2236 else 2543 else // no Av
2237 { 2544 {
2238 return; 2545 return;
2239 } 2546 }
2240 } 2547 }
2241 m_parentID = m_requestedSitTargetID;
2242 2548
2549 //We want our offsets to reference the root prim, not the child we may have sat on
2550 if (!part.IsRoot)
2551 {
2552 m_parentID = part.ParentGroup.RootPart.LocalId;
2553 m_pos += part.OffsetPosition;
2554 }
2555 else
2556 {
2557 m_parentID = m_requestedSitTargetID;
2558 }
2559
2560 m_linkedPrim = part.UUID;
2561 if (part.GetAvatarOnSitTarget() != UUID)
2562 {
2563 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2564 }
2243 Velocity = Vector3.Zero; 2565 Velocity = Vector3.Zero;
2244 RemoveFromPhysicalScene(); 2566 RemoveFromPhysicalScene();
2245
2246 Animator.TrySetMovementAnimation(sitAnimation); 2567 Animator.TrySetMovementAnimation(sitAnimation);
2247 SendAvatarDataToAllAgents(); 2568 SendAvatarDataToAllAgents();
2248 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2249 // So we're also sending a terse update (which has avatar rotation)
2250 // [Update] We do now.
2251 //SendTerseUpdateToAllClients(); 2569 //SendTerseUpdateToAllClients();
2252 } 2570 }
2571
2572 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2573 {
2574 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2575 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2576 if(hitYN)
2577 {
2578 // m_pos = Av offset from prim center to make look like on center
2579 // m_parentPosition = Actual center pos of prim
2580 // collisionPoint = spot on prim where we want to sit
2581 // collisionPoint.Z = global sit surface height
2582 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2583 Quaternion partIRot;
2584// if (part.LinkNum == 1)
2585/// { // Root prim of linkset
2586// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2587// }
2588// else
2589// { // single or child prim
2590 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2591// }
2592 if (m_initialSitTarget != null)
2593 {
2594 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2595 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2596 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2597 m_pos += offset;
2598 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2599 }
2600
2601 }
2602 } // End SitAltitudeCallback KF.
2253 2603
2254 /// <summary> 2604 /// <summary>
2255 /// Event handler for the 'Always run' setting on the client 2605 /// Event handler for the 'Always run' setting on the client
@@ -2369,6 +2719,9 @@ namespace OpenSim.Region.Framework.Scenes
2369 2719
2370 CheckForSignificantMovement(); // sends update to the modules. 2720 CheckForSignificantMovement(); // sends update to the modules.
2371 } 2721 }
2722
2723 //Sending prim updates AFTER the avatar terse updates are sent
2724 SendPrimUpdates();
2372 } 2725 }
2373 2726
2374 #endregion 2727 #endregion
@@ -3178,6 +3531,7 @@ namespace OpenSim.Region.Framework.Scenes
3178 m_callbackURI = cAgent.CallbackURI; 3531 m_callbackURI = cAgent.CallbackURI;
3179 3532
3180 m_pos = cAgent.Position; 3533 m_pos = cAgent.Position;
3534
3181 m_velocity = cAgent.Velocity; 3535 m_velocity = cAgent.Velocity;
3182 m_CameraCenter = cAgent.Center; 3536 m_CameraCenter = cAgent.Center;
3183 m_CameraAtAxis = cAgent.AtAxis; 3537 m_CameraAtAxis = cAgent.AtAxis;
@@ -3266,17 +3620,45 @@ namespace OpenSim.Region.Framework.Scenes
3266 /// </summary> 3620 /// </summary>
3267 public override void UpdateMovement() 3621 public override void UpdateMovement()
3268 { 3622 {
3269 if (m_forceToApply.HasValue) 3623 if (Animator!=null) // add for jumping
3270 { 3624 { // add for jumping
3271 Vector3 force = m_forceToApply.Value; 3625 // if (!m_animator.m_jumping) // add for jumping
3272 3626 // { // add for jumping
3273 m_updateflag = true;
3274 3627
3275 Velocity = force; 3628 if (m_forceToApply.HasValue) // this section realigned
3629 {
3276 3630
3277 m_forceToApply = null; 3631 Vector3 force = m_forceToApply.Value;
3278 } 3632 m_updateflag = true;
3279 } 3633if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3634 Velocity = force;
3635//Console.WriteLine("UM1 {0}", Velocity);
3636 m_forceToApply = null;
3637 }
3638 else
3639 {
3640 if (m_isNudging)
3641 {
3642 Vector3 force = Vector3.Zero;
3643
3644 m_updateflag = true;
3645if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3646 Velocity = force;
3647//Console.WriteLine("UM2 {0}", Velocity);
3648 m_isNudging = false;
3649 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3650 }
3651 else // add for jumping
3652 { // add for jumping
3653 Vector3 force = Vector3.Zero; // add for jumping
3654if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3655//Console.WriteLine("UM3 {0}", Velocity);
3656 Velocity = force; // add for jumping
3657 }
3658 }
3659 // } // end realign
3660 } // add for jumping
3661 } // add for jumping
3280 3662
3281 /// <summary> 3663 /// <summary>
3282 /// Adds a physical representation of the avatar to the Physics plugin 3664 /// Adds a physical representation of the avatar to the Physics plugin
@@ -3290,10 +3672,8 @@ namespace OpenSim.Region.Framework.Scenes
3290 3672
3291 Vector3 pVec = AbsolutePosition; 3673 Vector3 pVec = AbsolutePosition;
3292 3674
3293 // Old bug where the height was in centimeters instead of meters 3675 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3294 m_physicsActor = scene.AddAvatar(LocalId, Firstname + "." + Lastname, pVec,
3295 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3676 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3296
3297 scene.AddPhysicsActorTaint(m_physicsActor); 3677 scene.AddPhysicsActorTaint(m_physicsActor);
3298 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3678 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3299 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3679 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3319,18 +3699,29 @@ namespace OpenSim.Region.Framework.Scenes
3319 { 3699 {
3320 if (e == null) 3700 if (e == null)
3321 return; 3701 return;
3322 3702
3323 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3703 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3324 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3325 // as of this comment the interval is set in AddToPhysicalScene 3704 // as of this comment the interval is set in AddToPhysicalScene
3326 if (Animator!=null) 3705 if (Animator!=null)
3327 Animator.UpdateMovementAnimations(); 3706 {
3707 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3708 { // else its will lock out other animation changes, like ground sit.
3709 Animator.UpdateMovementAnimations();
3710 m_updateCount--;
3711 }
3712 }
3328 3713
3329 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3714 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3330 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3715 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3331 3716
3332 CollisionPlane = Vector4.UnitW; 3717 CollisionPlane = Vector4.UnitW;
3333 3718
3719 if (m_lastColCount != coldata.Count)
3720 {
3721 m_updateCount = UPDATE_COUNT;
3722 m_lastColCount = coldata.Count;
3723 }
3724
3334 if (coldata.Count != 0 && Animator != null) 3725 if (coldata.Count != 0 && Animator != null)
3335 { 3726 {
3336 switch (Animator.CurrentMovementAnimation) 3727 switch (Animator.CurrentMovementAnimation)
@@ -3360,6 +3751,148 @@ namespace OpenSim.Region.Framework.Scenes
3360 } 3751 }
3361 } 3752 }
3362 3753
3754 List<uint> thisHitColliders = new List<uint>();
3755 List<uint> endedColliders = new List<uint>();
3756 List<uint> startedColliders = new List<uint>();
3757
3758 foreach (uint localid in coldata.Keys)
3759 {
3760 thisHitColliders.Add(localid);
3761 if (!m_lastColliders.Contains(localid))
3762 {
3763 startedColliders.Add(localid);
3764 }
3765 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3766 }
3767
3768 // calculate things that ended colliding
3769 foreach (uint localID in m_lastColliders)
3770 {
3771 if (!thisHitColliders.Contains(localID))
3772 {
3773 endedColliders.Add(localID);
3774 }
3775 }
3776 //add the items that started colliding this time to the last colliders list.
3777 foreach (uint localID in startedColliders)
3778 {
3779 m_lastColliders.Add(localID);
3780 }
3781 // remove things that ended colliding from the last colliders list
3782 foreach (uint localID in endedColliders)
3783 {
3784 m_lastColliders.Remove(localID);
3785 }
3786
3787 // do event notification
3788 if (startedColliders.Count > 0)
3789 {
3790 ColliderArgs StartCollidingMessage = new ColliderArgs();
3791 List<DetectedObject> colliding = new List<DetectedObject>();
3792 foreach (uint localId in startedColliders)
3793 {
3794 if (localId == 0)
3795 continue;
3796
3797 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3798 string data = "";
3799 if (obj != null)
3800 {
3801 DetectedObject detobj = new DetectedObject();
3802 detobj.keyUUID = obj.UUID;
3803 detobj.nameStr = obj.Name;
3804 detobj.ownerUUID = obj.OwnerID;
3805 detobj.posVector = obj.AbsolutePosition;
3806 detobj.rotQuat = obj.GetWorldRotation();
3807 detobj.velVector = obj.Velocity;
3808 detobj.colliderType = 0;
3809 detobj.groupUUID = obj.GroupID;
3810 colliding.Add(detobj);
3811 }
3812 }
3813
3814 if (colliding.Count > 0)
3815 {
3816 StartCollidingMessage.Colliders = colliding;
3817
3818 foreach (SceneObjectGroup att in GetAttachments())
3819 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3820 }
3821 }
3822
3823 if (endedColliders.Count > 0)
3824 {
3825 ColliderArgs EndCollidingMessage = new ColliderArgs();
3826 List<DetectedObject> colliding = new List<DetectedObject>();
3827 foreach (uint localId in endedColliders)
3828 {
3829 if (localId == 0)
3830 continue;
3831
3832 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3833 string data = "";
3834 if (obj != null)
3835 {
3836 DetectedObject detobj = new DetectedObject();
3837 detobj.keyUUID = obj.UUID;
3838 detobj.nameStr = obj.Name;
3839 detobj.ownerUUID = obj.OwnerID;
3840 detobj.posVector = obj.AbsolutePosition;
3841 detobj.rotQuat = obj.GetWorldRotation();
3842 detobj.velVector = obj.Velocity;
3843 detobj.colliderType = 0;
3844 detobj.groupUUID = obj.GroupID;
3845 colliding.Add(detobj);
3846 }
3847 }
3848
3849 if (colliding.Count > 0)
3850 {
3851 EndCollidingMessage.Colliders = colliding;
3852
3853 foreach (SceneObjectGroup att in GetAttachments())
3854 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3855 }
3856 }
3857
3858 if (thisHitColliders.Count > 0)
3859 {
3860 ColliderArgs CollidingMessage = new ColliderArgs();
3861 List<DetectedObject> colliding = new List<DetectedObject>();
3862 foreach (uint localId in thisHitColliders)
3863 {
3864 if (localId == 0)
3865 continue;
3866
3867 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3868 string data = "";
3869 if (obj != null)
3870 {
3871 DetectedObject detobj = new DetectedObject();
3872 detobj.keyUUID = obj.UUID;
3873 detobj.nameStr = obj.Name;
3874 detobj.ownerUUID = obj.OwnerID;
3875 detobj.posVector = obj.AbsolutePosition;
3876 detobj.rotQuat = obj.GetWorldRotation();
3877 detobj.velVector = obj.Velocity;
3878 detobj.colliderType = 0;
3879 detobj.groupUUID = obj.GroupID;
3880 colliding.Add(detobj);
3881 }
3882 }
3883
3884 if (colliding.Count > 0)
3885 {
3886 CollidingMessage.Colliders = colliding;
3887
3888 lock (m_attachments)
3889 {
3890 foreach (SceneObjectGroup att in m_attachments)
3891 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3892 }
3893 }
3894 }
3895
3363 if (m_invulnerable) 3896 if (m_invulnerable)
3364 return; 3897 return;
3365 3898
@@ -3433,6 +3966,10 @@ namespace OpenSim.Region.Framework.Scenes
3433 { 3966 {
3434 lock (m_attachments) 3967 lock (m_attachments)
3435 { 3968 {
3969 // This may be true when the attachment comes back
3970 // from serialization after login. Clear it.
3971 gobj.IsDeleted = false;
3972
3436 m_attachments.Add(gobj); 3973 m_attachments.Add(gobj);
3437 } 3974 }
3438 } 3975 }
@@ -3796,5 +4333,39 @@ namespace OpenSim.Region.Framework.Scenes
3796 m_reprioritization_called = false; 4333 m_reprioritization_called = false;
3797 } 4334 }
3798 } 4335 }
4336
4337 private Vector3 Quat2Euler(Quaternion rot){
4338 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4339 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4340 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4341 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4342 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4343 return(new Vector3(x,y,z));
4344 }
4345
4346 private void CheckLandingPoint(ref Vector3 pos)
4347 {
4348 // Never constrain lures
4349 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
4350 return;
4351
4352 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
4353 return;
4354
4355 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
4356
4357 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
4358 land.LandData.UserLocation != Vector3.Zero &&
4359 land.LandData.OwnerID != m_uuid &&
4360 (!m_scene.Permissions.IsGod(m_uuid)) &&
4361 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)))
4362 {
4363 float curr = Vector3.Distance(AbsolutePosition, pos);
4364 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
4365 pos = land.LandData.UserLocation;
4366 else
4367 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
4368 }
4369 }
3799 } 4370 }
3800} \ No newline at end of file 4371} \ No newline at end of file
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;