aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs20
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs13
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs226
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs11
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs34
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs253
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs507
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs230
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs670
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs296
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs754
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs1026
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs16
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs168
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
26 files changed, 3163 insertions, 1210 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 6cc64c6..788f42b 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using OpenMetaverse; 30using OpenMetaverse;
30using OpenMetaverse.Packets; 31using OpenMetaverse.Packets;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -82,6 +83,10 @@ namespace OpenSim.Region.Framework.Interfaces
82 UUID RezSingleAttachmentFromInventory( 83 UUID RezSingleAttachmentFromInventory(
83 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus); 84 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus);
84 85
86 // Same as above, but also load script states from a separate doc
87 UUID RezSingleAttachmentFromInventory(
88 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
89
85 /// <summary> 90 /// <summary>
86 /// Rez multiple attachments from a user's inventory 91 /// Rez multiple attachments from a user's inventory
87 /// </summary> 92 /// </summary>
@@ -113,18 +118,15 @@ namespace OpenSim.Region.Framework.Interfaces
113 /// <summary> 118 /// <summary>
114 /// Update the user inventory to show a detach. 119 /// Update the user inventory to show a detach.
115 /// </summary> 120 /// </summary>
116 /// <param name="itemID">/param> 121 /// <param name="itemID">
117 /// <param name="remoteClient"></param> 122 /// A <see cref="UUID"/>
123 /// </param>
124 /// <param name="remoteClient">
125 /// A <see cref="IClientAPI"/>
126 /// </param>
118 void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient); 127 void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient);
119 128
120 /// <summary> 129 /// <summary>
121 /// Update the position of an attachment.
122 /// </summary>
123 /// <param name="sog"></param>
124 /// <param name="pos"></param>
125 void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos);
126
127 /// <summary>
128 /// Update the user inventory with a changed attachment 130 /// Update the user inventory with a changed attachment
129 /// </summary> 131 /// </summary>
130 /// <param name="remoteClient"> 132 /// <param name="remoteClient">
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
index 15060fd..4b17b9a 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs
@@ -115,6 +115,8 @@ namespace OpenSim.Region.Framework.Interfaces
115 /// <param name="stateSource"></param> 115 /// <param name="stateSource"></param>
116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); 116 void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
117 117
118 ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource);
119
118 /// <summary> 120 /// <summary>
119 /// Stop a script which is in this prim's inventory. 121 /// Stop a script which is in this prim's inventory.
120 /// </summary> 122 /// </summary>
@@ -229,5 +231,6 @@ namespace OpenSim.Region.Framework.Interfaces
229 /// A <see cref="Dictionary`2"/> 231 /// A <see cref="Dictionary`2"/>
230 /// </returns> 232 /// </returns>
231 Dictionary<UUID, string> GetScriptStates(); 233 Dictionary<UUID, string> GetScriptStates();
234 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
232 } 235 }
233} 236}
diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
index 8b96de4..3eb38b8 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces
40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, 40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position,
41 Vector3 lookAt, uint teleportFlags); 41 Vector3 lookAt, uint teleportFlags);
42 42
43 void TeleportHome(UUID id, IClientAPI client); 43 bool TeleportHome(UUID id, IClientAPI client);
44 44
45 bool Cross(ScenePresence agent, bool isFlying); 45 bool Cross(ScenePresence agent, bool isFlying);
46 46
diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
index 2d6287f..67a500f 100644
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
@@ -68,6 +68,14 @@ namespace OpenSim.Region.Framework.Interfaces
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); 68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69 69
70 /// <summary> 70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
71 /// Close agent. 79 /// Close agent.
72 /// </summary> 80 /// </summary>
73 /// <param name="regionHandle"></param> 81 /// <param name="regionHandle"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index fecdd1b..4a3c634 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -50,5 +50,7 @@ namespace OpenSim.Region.Framework.Interfaces
50 void ResumeScript(UUID itemID); 50 void ResumeScript(UUID itemID);
51 51
52 ArrayList GetScriptErrors(UUID itemID); 52 ArrayList GetScriptErrors(UUID itemID);
53
54 bool HasScript(UUID itemID, out bool running);
53 } 55 }
54} 56}
diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
new file mode 100644
index 0000000..e01f649
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs
@@ -0,0 +1,27 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster LImited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6// Mod 2
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface ISnmpModule
11{
12 void Trap(int code, string Message, Scene scene);
13 void Critical(string Message, Scene scene);
14 void Warning(string Message, Scene scene);
15 void Major(string Message, Scene scene);
16 void ColdStart(int step , Scene scene);
17 void Shutdown(int step , Scene scene);
18 //
19 // Node Start/stop events
20 //
21 void LinkUp(Scene scene);
22 void LinkDown(Scene scene);
23 void BootInfo(string data, Scene scene);
24 void trapDebug(string Module,string data, Scene scene);
25 void trapXMRE(int data, string Message, Scene scene);
26
27}
diff --git a/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
new file mode 100644
index 0000000..d1a4d8e
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs
@@ -0,0 +1,13 @@
1///////////////////////////////////////////////////////////////////
2//
3// (c) Careminster Limited, Melanie Thielker and the Meta7 Team
4//
5// This file is not open source. All rights reserved
6//
7
8using OpenSim.Region.Framework.Scenes;
9
10public interface IUserAccountCacheModule
11{
12 void Remove(string name);
13}
diff --git a/OpenSim/Region/Framework/ModuleLoader.cs b/OpenSim/Region/Framework/ModuleLoader.cs
index 23be9c2..69ba2042 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -226,7 +226,8 @@ namespace OpenSim.Region.Framework
226 "[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e); 226 "[MODULES]: Could not load types for [{0}]. Exception {1}", pluginAssembly.FullName, e);
227 227
228 // justincc: Right now this is fatal to really get the user's attention 228 // justincc: Right now this is fatal to really get the user's attention
229 throw e; 229 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
230 //throw e;
230 } 231 }
231 } 232 }
232 233
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 4865481..9c103cb 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -53,11 +53,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
53 { 53 {
54 get { return m_movementAnimation; } 54 get { return m_movementAnimation; }
55 } 55 }
56 protected string m_movementAnimation = "DEFAULT"; 56 // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist!
57 57 protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init.
58 private int m_animTickFall; 58 private int m_animTickFall;
59 private int m_animTickJump; 59// private int m_animTickJump;
60 60 public int m_animTickJump; // ScenePresence has to see this to control +Z force
61 public bool m_jumping = false; // Add for jumping
62 public float m_jumpVelocity = 0f; // Add for jumping
63 private int m_landing = 0; // Add for jumping
64 public bool m_falling = false; // Add for falling
65 private float m_fallHeight; // Add for falling
66
61 /// <value> 67 /// <value>
62 /// The scene presence that this animator applies to 68 /// The scene presence that this animator applies to
63 /// </value> 69 /// </value>
@@ -114,7 +120,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation
114 120
115 public void ResetAnimations() 121 public void ResetAnimations()
116 { 122 {
123Console.WriteLine("ResetA.............");
117 m_animations.Clear(); 124 m_animations.Clear();
125TrySetMovementAnimation("STAND");
118 } 126 }
119 127
120 /// <summary> 128 /// <summary>
@@ -123,8 +131,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation
123 /// </summary> 131 /// </summary>
124 public void TrySetMovementAnimation(string anim) 132 public void TrySetMovementAnimation(string anim)
125 { 133 {
126 //m_log.DebugFormat("Updating movement animation to {0}", anim);
127
128 if (!m_scenePresence.IsChildAgent) 134 if (!m_scenePresence.IsChildAgent)
129 { 135 {
130 if (m_animations.TrySetDefaultAnimation( 136 if (m_animations.TrySetDefaultAnimation(
@@ -142,14 +148,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
142 /// </summary> 148 /// </summary>
143 public string GetMovementAnimation() 149 public string GetMovementAnimation()
144 { 150 {
145 const float FALL_DELAY = 0.33f; 151//Console.WriteLine("GMA-------"); //##
146 const float PREJUMP_DELAY = 0.25f; 152//#@ const float FALL_DELAY = 0.33f;
147 153 const float FALL_DELAY = 800f; //## mS
154//rm for jumping const float PREJUMP_DELAY = 0.25f;
155 const float PREJUMP_DELAY = 200f; // mS add for jumping
156 const float JUMP_PERIOD = 800f; // mS add for jumping
148 #region Inputs 157 #region Inputs
149 if (m_scenePresence.SitGround) 158
150 {
151 return "SIT_GROUND_CONSTRAINED";
152 }
153 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 159 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
154 PhysicsActor actor = m_scenePresence.PhysicsActor; 160 PhysicsActor actor = m_scenePresence.PhysicsActor;
155 161
@@ -159,11 +165,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
159 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 165 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
160 166
161 // Check control flags 167 // Check control flags
162 bool heldForward = 168 bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS);
163 (((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) || ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS)); 169 bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
164 bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; 170 bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
165 bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; 171 bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG);
166 bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
167 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 172 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
168 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 173 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
169 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 174 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -182,8 +187,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
182 187
183 // Is the avatar trying to move? 188 // Is the avatar trying to move?
184// bool moving = (move != Vector3.Zero); 189// bool moving = (move != Vector3.Zero);
185 bool jumping = m_animTickJump != 0; 190// rm for jumping bool jumping = m_animTickJump != 0;
186
187 #endregion Inputs 191 #endregion Inputs
188 192
189 #region Flying 193 #region Flying
@@ -192,6 +196,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
192 { 196 {
193 m_animTickFall = 0; 197 m_animTickFall = 0;
194 m_animTickJump = 0; 198 m_animTickJump = 0;
199 m_jumping = false; //add for jumping
200 m_falling = true; //add for falling
201 m_jumpVelocity = 0f; //add for jumping
202 actor.Selected = false; //add for jumping flag
203 m_fallHeight = actor.Position.Z; // save latest flying height
195 204
196 if (move.X != 0f || move.Y != 0f) 205 if (move.X != 0f || move.Y != 0f)
197 { 206 {
@@ -203,8 +212,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
203 } 212 }
204 else if (move.Z < 0f) 213 else if (move.Z < 0f)
205 { 214 {
206 if (actor != null && actor.IsColliding) 215 if (actor != null && actor.IsColliding)
216 { //##
217//Console.WriteLine("LAND FLYING"); // ##
207 return "LAND"; 218 return "LAND";
219 } //#
208 else 220 else
209 return "HOVER_DOWN"; 221 return "HOVER_DOWN";
210 } 222 }
@@ -218,48 +230,127 @@ namespace OpenSim.Region.Framework.Scenes.Animation
218 230
219 #region Falling/Floating/Landing 231 #region Falling/Floating/Landing
220 232
221 if (actor == null || !actor.IsColliding) 233// rm for jumping if (actor == null || !actor.IsColliding)
234 if ((actor == null || !actor.IsColliding) && !m_jumping) // add for jumping
222 { 235 {
223 float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 236// rm float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
237 float fallElapsed = (float)(Environment.TickCount - m_animTickFall); // add, in mS
224 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; 238 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
239//Console.WriteLine("falling t={0} v={1}", fallElapsed, fallVelocity); //##
240
241// rm for fall if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f))
242 if (!m_jumping && (fallVelocity < -3.0f) ) m_falling = true; // add for falling and jumping
225 243
226 if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f)) 244 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) // add for jumping
245 // not falling yet or going up
227 { 246 {
228 // Just started falling 247 // reset start of fall time
229 m_animTickFall = Environment.TickCount; 248 m_animTickFall = Environment.TickCount;
230 } 249 }
231 else if (!jumping && fallElapsed > FALL_DELAY) 250// else if (!jumping && fallElapsed > FALL_DELAY)
251 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.m_wasFlying)) // add for falling and jumping
232 { 252 {
233 // Falling long enough to trigger the animation 253 // Falling long enough to trigger the animation
254//Console.WriteLine("FALLDOWN"); //##
234 return "FALLDOWN"; 255 return "FALLDOWN";
235 } 256 }
236 else if (m_animTickJump == -1)
237 {
238 m_animTickJump = 0;
239 return "STAND";
240 }
241 257
242 return m_movementAnimation; 258 return m_movementAnimation;
243 } 259 }
244 260
245 #endregion Falling/Floating/Landing 261 #endregion Falling/Floating/Landing
246 262
263
264 #region Jumping // section added for jumping...
265
266 int jumptime;
267 jumptime = Environment.TickCount - m_animTickJump;
268
269
270 if ((move.Z > 0f) && (!m_jumping))
271 {
272//Console.WriteLine("PJ {0}", jumptime); //##
273 // Start jumping, prejump
274 m_animTickFall = 0;
275 m_jumping = true;
276 m_falling = false;
277 actor.Selected = true; // borrowed for jmping flag
278 m_animTickJump = Environment.TickCount;
279 m_jumpVelocity = 0.35f;
280 return "PREJUMP";
281 }
282
283 if(m_jumping)
284 {
285 if ( (jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
286 {
287//Console.WriteLine("LA {0}", jumptime); //##
288 // end jumping
289 m_jumping = false;
290 m_falling = false;
291 actor.Selected = false; // borrowed for jumping flag
292 m_jumpVelocity = 0f;
293 m_animTickFall = Environment.TickCount;
294 return "LAND";
295 }
296 else if (jumptime > JUMP_PERIOD)
297 {
298//Console.WriteLine("JD {0}", jumptime); //##
299 // jump down
300 m_jumpVelocity = 0f;
301 return "JUMP";
302 }
303 else if (jumptime > PREJUMP_DELAY)
304 {
305//Console.WriteLine("JU {0}", jumptime); //##
306 // jump up
307 m_jumping = true;
308 m_jumpVelocity = 10f;
309 return "JUMP";
310 }
311 }
312
313 #endregion Jumping // end added section
314
247 #region Ground Movement 315 #region Ground Movement
248 316
249 if (m_movementAnimation == "FALLDOWN") 317 if (m_movementAnimation == "FALLDOWN")
250 { 318 {
319 m_falling = false;
251 m_animTickFall = Environment.TickCount; 320 m_animTickFall = Environment.TickCount;
252
253 // TODO: SOFT_LAND support 321 // TODO: SOFT_LAND support
254 return "LAND"; 322 float fallHeight = m_fallHeight - actor.Position.Z;
323//Console.WriteLine("Hit from {0}", fallHeight); //##
324 if (fallHeight > 15.0f) // add for falling
325 return "STANDUP";
326 else if (fallHeight > 8.0f) // add for falling
327 return "SOFT_LAND"; // add for falling
328 else // add for falling
329 return "LAND"; // add for falling
255 } 330 }
256 else if (m_movementAnimation == "LAND") 331// rm jumping float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
332// rm jumping if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY))
333// rm for landing return "LAND";
334 else if ((m_movementAnimation == "LAND") || (m_movementAnimation == "SOFT_LAND") || (m_movementAnimation == "STANDUP"))
257 { 335 {
258 float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 336 int landElapsed = Environment.TickCount - m_animTickFall; // add for jumping
259 if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) 337 int limit = 1000; // add for jumping
260 return "LAND"; 338 if(m_movementAnimation == "LAND") limit = 350; // add for jumping
261 } 339 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
262 340
341 if ((m_animTickFall != 0) && (landElapsed <= limit)) // add for jumping
342 {
343//Console.WriteLine("Lelapse {0}", m_movementAnimation); //##
344 return m_movementAnimation;
345 }
346 else
347 {
348//Console.WriteLine("end/STAND"); //##
349 m_fallHeight = actor.Position.Z; // save latest flying height
350 return "STAND";
351 }
352 }
353/* This section removed, replaced by jumping section
263 m_animTickFall = 0; 354 m_animTickFall = 0;
264 355
265 if (move.Z > 0f) 356 if (move.Z > 0f)
@@ -271,7 +362,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
271 m_animTickJump = Environment.TickCount; 362 m_animTickJump = Environment.TickCount;
272 return "PREJUMP"; 363 return "PREJUMP";
273 } 364 }
274 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) 365 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 800.0f)
275 { 366 {
276 // Start actual jump 367 // Start actual jump
277 if (m_animTickJump == -1) 368 if (m_animTickJump == -1)
@@ -284,37 +375,40 @@ namespace OpenSim.Region.Framework.Scenes.Animation
284 m_animTickJump = -1; 375 m_animTickJump = -1;
285 return "JUMP"; 376 return "JUMP";
286 } 377 }
287 else
288 return "JUMP";
289 } 378 }
290 else 379 else
291 { 380 {
292 // Not jumping 381 // Not jumping
293 m_animTickJump = 0; 382 m_animTickJump = 0;
294 383 */
295 if (move.X != 0f || move.Y != 0f) 384 // next section moved outside paren. and realigned for jumping
296 { 385 if (move.X != 0f || move.Y != 0f)
297 // Walking / crouchwalking / running 386 {
298 if (move.Z < 0f) 387 m_fallHeight = actor.Position.Z; // save latest flying height
299 return "CROUCHWALK"; 388 m_falling = false; // Add for falling
300 else if (m_scenePresence.SetAlwaysRun) 389 // Walking / crouchwalking / running
301 return "RUN"; 390 if (move.Z < 0f)
302 else 391 return "CROUCHWALK";
303 return "WALK"; 392 else if (m_scenePresence.SetAlwaysRun)
304 } 393 return "RUN";
305 else 394 else
306 { 395 return "WALK";
307 // Not walking
308 if (move.Z < 0f)
309 return "CROUCH";
310 else
311 return "STAND";
312 }
313 } 396 }
314 397// rm for jumping else
398 else if (!m_jumping) // add for jumping
399 {
400 m_falling = false; // Add for falling
401 // Not walking
402 if (move.Z < 0f)
403 return "CROUCH";
404 else
405 return "STAND";
406 }
407 // end section realign for jumping
315 #endregion Ground Movement 408 #endregion Ground Movement
316 409
317 //return m_movementAnimation; 410 m_falling = false; // Add for falling
411 return m_movementAnimation;
318 } 412 }
319 413
320 /// <summary> 414 /// <summary>
@@ -323,7 +417,15 @@ namespace OpenSim.Region.Framework.Scenes.Animation
323 public void UpdateMovementAnimations() 417 public void UpdateMovementAnimations()
324 { 418 {
325 m_movementAnimation = GetMovementAnimation(); 419 m_movementAnimation = GetMovementAnimation();
326 TrySetMovementAnimation(m_movementAnimation); 420/* if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
421 {
422 // This was the previous behavior before PREJUMP
423 TrySetMovementAnimation("JUMP");
424 }
425 else
426 { removed for jumping */
427 TrySetMovementAnimation(m_movementAnimation);
428// rm for jumping }
327 } 429 }
328 430
329 public UUID[] GetAnimationArray() 431 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 64567db..a8d24fd 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,8 +104,15 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
107 foreach (SceneObjectGroup g in objectGroups) 109 foreach (SceneObjectGroup g in objectGroups)
110 {
111 killIDs.Add(g.LocalId);
108 g.DeleteGroupFromScene(false); 112 g.DeleteGroupFromScene(false);
113 }
114
115 m_scene.SendKillObject(killIDs);
109 } 116 }
110 } 117 }
111 118
@@ -137,7 +144,7 @@ namespace OpenSim.Region.Framework.Scenes
137 x = m_inventoryDeletes.Dequeue(); 144 x = m_inventoryDeletes.Dequeue();
138 145
139 m_log.DebugFormat( 146 m_log.DebugFormat(
140 "[ASYNC DELETER]: Sending object to user's inventory, {0} item(s) remaining.", left); 147 "[ASYNC DELETER]: Sending object to user's inventory, action {1}, count {2}, {0} item(s) remaining.", left, x.action, x.objectGroups.Count);
141 148
142 try 149 try
143 { 150 {
@@ -177,4 +184,4 @@ namespace OpenSim.Region.Framework.Scenes
177 return false; 184 return false;
178 } 185 }
179 } 186 }
180} \ No newline at end of file 187}
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index c321a15..f24c53c 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -55,8 +55,12 @@ namespace OpenSim.Region.Framework.Scenes
55 55
56 public delegate void OnTerrainTickDelegate(); 56 public delegate void OnTerrainTickDelegate();
57 57
58 public delegate void OnTerrainUpdateDelegate();
59
58 public event OnTerrainTickDelegate OnTerrainTick; 60 public event OnTerrainTickDelegate OnTerrainTick;
59 61
62 public event OnTerrainUpdateDelegate OnTerrainUpdate;
63
60 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 64 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
61 65
62 public event OnBackupDelegate OnBackup; 66 public event OnBackupDelegate OnBackup;
@@ -757,6 +761,26 @@ namespace OpenSim.Region.Framework.Scenes
757 } 761 }
758 } 762 }
759 } 763 }
764 public void TriggerTerrainUpdate()
765 {
766 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
767 if (handlerTerrainUpdate != null)
768 {
769 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
770 {
771 try
772 {
773 d();
774 }
775 catch (Exception e)
776 {
777 m_log.ErrorFormat(
778 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
779 e.Message, e.StackTrace);
780 }
781 }
782 }
783 }
760 784
761 public void TriggerTerrainTick() 785 public void TriggerTerrainTick()
762 { 786 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index f9599f5..cde8d3f 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -167,6 +167,7 @@ namespace OpenSim.Region.Framework.Scenes
167 167
168 private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity) 168 private double GetPriorityByFrontBack(IClientAPI client, ISceneEntity entity)
169 { 169 {
170 if (entity == null) return double.NaN;
170 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 171 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
171 if (presence != null) 172 if (presence != null)
172 { 173 {
@@ -224,22 +225,16 @@ namespace OpenSim.Region.Framework.Scenes
224 if (entity == null) 225 if (entity == null)
225 return double.NaN; 226 return double.NaN;
226 227
227 // Use group position for child prims 228 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
228 Vector3 entityPos = entity.AbsolutePosition; 229 if (presence != null)
229 if (entity is SceneObjectPart)
230 { 230 {
231 SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup; 231 // Use group position for child prims
232 if (group != null) 232 Vector3 entityPos;
233 entityPos = group.AbsolutePosition; 233 if (entity is SceneObjectPart)
234 entityPos = ((SceneObjectPart)entity).ParentGroup.AbsolutePosition;
234 else 235 else
235 entityPos = entity.AbsolutePosition; 236 entityPos = entity.AbsolutePosition;
236 }
237 else
238 entityPos = entity.AbsolutePosition;
239 237
240 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
241 if (presence != null)
242 {
243 if (!presence.IsChildAgent) 238 if (!presence.IsChildAgent)
244 { 239 {
245 if (entity is ScenePresence) 240 if (entity is ScenePresence)
@@ -259,12 +254,19 @@ namespace OpenSim.Region.Framework.Scenes
259 254
260 if (entity is SceneObjectPart) 255 if (entity is SceneObjectPart)
261 { 256 {
262 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
263 if (physActor == null || !physActor.IsPhysical)
264 priority += 100;
265
266 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) 257 if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment)
258 {
267 priority = 1.0; 259 priority = 1.0;
260 }
261 else
262 {
263 PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor;
264 if (physActor == null || !physActor.IsPhysical)
265 priority += 100;
266 }
267
268 if (((SceneObjectPart)entity).ParentGroup.RootPart != (SceneObjectPart)entity)
269 priority +=1;
268 } 270 }
269 return priority; 271 return priority;
270 } 272 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index e2d96d9..9a93a26 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -99,34 +99,22 @@ namespace OpenSim.Region.Framework.Scenes
99 /// <param name="item"></param> 99 /// <param name="item"></param>
100 public bool AddInventoryItem(InventoryItemBase item) 100 public bool AddInventoryItem(InventoryItemBase item)
101 { 101 {
102 if (UUID.Zero == item.Folder) 102 InventoryFolderBase folder;
103
104 if (item.Folder == UUID.Zero)
103 { 105 {
104 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 106 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
105 if (f != null) 107 if (folder == null)
106 {
107// m_log.DebugFormat(
108// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}",
109// f.Name, (AssetType)f.Type, item.Name);
110
111 item.Folder = f.ID;
112 }
113 else
114 { 108 {
115 f = InventoryService.GetRootFolder(item.Owner); 109 folder = InventoryService.GetRootFolder(item.Owner);
116 if (f != null) 110
117 { 111 if (folder == null)
118 item.Folder = f.ID;
119 }
120 else
121 {
122 m_log.WarnFormat(
123 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
124 item.Owner, item.Name);
125 return false; 112 return false;
126 }
127 } 113 }
114
115 item.Folder = folder.ID;
128 } 116 }
129 117
130 if (InventoryService.AddItem(item)) 118 if (InventoryService.AddItem(item))
131 { 119 {
132 int userlevel = 0; 120 int userlevel = 0;
@@ -252,8 +240,7 @@ namespace OpenSim.Region.Framework.Scenes
252 240
253 // Update item with new asset 241 // Update item with new asset
254 item.AssetID = asset.FullID; 242 item.AssetID = asset.FullID;
255 if (group.UpdateInventoryItem(item)) 243 group.UpdateInventoryItem(item);
256 remoteClient.SendAgentAlertMessage("Script saved", false);
257 244
258 part.GetProperties(remoteClient); 245 part.GetProperties(remoteClient);
259 246
@@ -264,12 +251,7 @@ namespace OpenSim.Region.Framework.Scenes
264 { 251 {
265 // Needs to determine which engine was running it and use that 252 // Needs to determine which engine was running it and use that
266 // 253 //
267 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 254 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
268 errors = part.Inventory.GetScriptErrors(item.ItemID);
269 }
270 else
271 {
272 remoteClient.SendAgentAlertMessage("Script saved", false);
273 } 255 }
274 part.ParentGroup.ResumeScripts(); 256 part.ParentGroup.ResumeScripts();
275 return errors; 257 return errors;
@@ -326,6 +308,7 @@ namespace OpenSim.Region.Framework.Scenes
326 { 308 {
327 if (UUID.Zero == transactionID) 309 if (UUID.Zero == transactionID)
328 { 310 {
311 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
329 item.Name = itemUpd.Name; 312 item.Name = itemUpd.Name;
330 item.Description = itemUpd.Description; 313 item.Description = itemUpd.Description;
331 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 314 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -698,6 +681,8 @@ namespace OpenSim.Region.Framework.Scenes
698 return; 681 return;
699 } 682 }
700 683
684 if (newName == null) newName = item.Name;
685
701 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 686 AssetBase asset = AssetService.Get(item.AssetID.ToString());
702 687
703 if (asset != null) 688 if (asset != null)
@@ -751,6 +736,24 @@ namespace OpenSim.Region.Framework.Scenes
751 } 736 }
752 737
753 /// <summary> 738 /// <summary>
739 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
740 /// </summary>
741 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
742 {
743 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
744 foreach (InventoryItemBase b in items)
745 {
746 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
747 InventoryItemBase n = InventoryService.GetItem(b);
748 n.Folder = destfolder;
749 moveitems.Add(n);
750 remoteClient.SendInventoryItemCreateUpdate(n, 0);
751 }
752
753 MoveInventoryItem(remoteClient, moveitems);
754 }
755
756 /// <summary>
754 /// Move an item within the agent's inventory. 757 /// Move an item within the agent's inventory.
755 /// </summary> 758 /// </summary>
756 /// <param name="remoteClient"></param> 759 /// <param name="remoteClient"></param>
@@ -983,8 +986,12 @@ namespace OpenSim.Region.Framework.Scenes
983 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 986 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
984 { 987 {
985 SceneObjectPart part = GetSceneObjectPart(localID); 988 SceneObjectPart part = GetSceneObjectPart(localID);
986 SceneObjectGroup group = part.ParentGroup; 989 SceneObjectGroup group = null;
987 if (group != null) 990 if (part != null)
991 {
992 group = part.ParentGroup;
993 }
994 if (part != null && group != null)
988 { 995 {
989 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 996 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
990 return; 997 return;
@@ -1433,13 +1440,6 @@ namespace OpenSim.Region.Framework.Scenes
1433 { 1440 {
1434 agentTransactions.HandleTaskItemUpdateFromTransaction( 1441 agentTransactions.HandleTaskItemUpdateFromTransaction(
1435 remoteClient, part, transactionID, currentItem); 1442 remoteClient, part, transactionID, currentItem);
1436
1437 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1438 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1439 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1440 remoteClient.SendAgentAlertMessage("Script saved", false);
1441 else
1442 remoteClient.SendAgentAlertMessage("Item saved", false);
1443 } 1443 }
1444 1444
1445 // Base ALWAYS has move 1445 // Base ALWAYS has move
@@ -1580,7 +1580,7 @@ namespace OpenSim.Region.Framework.Scenes
1580 return; 1580 return;
1581 1581
1582 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1582 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1583 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1583 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1584 remoteClient.AgentId); 1584 remoteClient.AgentId);
1585 AssetService.Store(asset); 1585 AssetService.Store(asset);
1586 1586
@@ -1733,23 +1733,32 @@ namespace OpenSim.Region.Framework.Scenes
1733 // build a list of eligible objects 1733 // build a list of eligible objects
1734 List<uint> deleteIDs = new List<uint>(); 1734 List<uint> deleteIDs = new List<uint>();
1735 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1735 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1736 1736 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1737 // Start with true for both, then remove the flags if objects
1738 // that we can't derez are part of the selection
1739 bool permissionToTake = true;
1740 bool permissionToTakeCopy = true;
1741 bool permissionToDelete = true;
1742 1737
1743 foreach (uint localID in localIDs) 1738 foreach (uint localID in localIDs)
1744 { 1739 {
1740 // Start with true for both, then remove the flags if objects
1741 // that we can't derez are part of the selection
1742 bool permissionToTake = true;
1743 bool permissionToTakeCopy = true;
1744 bool permissionToDelete = true;
1745
1745 // Invalid id 1746 // Invalid id
1746 SceneObjectPart part = GetSceneObjectPart(localID); 1747 SceneObjectPart part = GetSceneObjectPart(localID);
1747 if (part == null) 1748 if (part == null)
1749 {
1750 //Client still thinks the object exists, kill it
1751 deleteIDs.Add(localID);
1748 continue; 1752 continue;
1753 }
1749 1754
1750 // Already deleted by someone else 1755 // Already deleted by someone else
1751 if (part.ParentGroup == null || part.ParentGroup.IsDeleted) 1756 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
1757 {
1758 //Client still thinks the object exists, kill it
1759 deleteIDs.Add(localID);
1752 continue; 1760 continue;
1761 }
1753 1762
1754 // Can't delete child prims 1763 // Can't delete child prims
1755 if (part != part.ParentGroup.RootPart) 1764 if (part != part.ParentGroup.RootPart)
@@ -1757,9 +1766,6 @@ namespace OpenSim.Region.Framework.Scenes
1757 1766
1758 SceneObjectGroup grp = part.ParentGroup; 1767 SceneObjectGroup grp = part.ParentGroup;
1759 1768
1760 deleteIDs.Add(localID);
1761 deleteGroups.Add(grp);
1762
1763 if (remoteClient == null) 1769 if (remoteClient == null)
1764 { 1770 {
1765 // Autoreturn has a null client. Nothing else does. So 1771 // Autoreturn has a null client. Nothing else does. So
@@ -1776,80 +1782,104 @@ namespace OpenSim.Region.Framework.Scenes
1776 } 1782 }
1777 else 1783 else
1778 { 1784 {
1779 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1785 if (action == DeRezAction.TakeCopy)
1786 {
1787 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1788 permissionToTakeCopy = false;
1789 }
1790 else
1791 {
1780 permissionToTakeCopy = false; 1792 permissionToTakeCopy = false;
1781 1793 }
1782 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1794 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1783 permissionToTake = false; 1795 permissionToTake = false;
1784 1796
1785 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1797 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1786 permissionToDelete = false; 1798 permissionToDelete = false;
1787 } 1799 }
1788 }
1789 1800
1790 // Handle god perms 1801 // Handle god perms
1791 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1802 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1792 { 1803 {
1793 permissionToTake = true; 1804 permissionToTake = true;
1794 permissionToTakeCopy = true; 1805 permissionToTakeCopy = true;
1795 permissionToDelete = true; 1806 permissionToDelete = true;
1796 } 1807 }
1797 1808
1798 // If we're re-saving, we don't even want to delete 1809 // If we're re-saving, we don't even want to delete
1799 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1810 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1800 permissionToDelete = false; 1811 permissionToDelete = false;
1801 1812
1802 // if we want to take a copy, we also don't want to delete 1813 // if we want to take a copy, we also don't want to delete
1803 // Note: after this point, the permissionToTakeCopy flag 1814 // Note: after this point, the permissionToTakeCopy flag
1804 // becomes irrelevant. It already includes the permissionToTake 1815 // becomes irrelevant. It already includes the permissionToTake
1805 // permission and after excluding no copy items here, we can 1816 // permission and after excluding no copy items here, we can
1806 // just use that. 1817 // just use that.
1807 if (action == DeRezAction.TakeCopy) 1818 if (action == DeRezAction.TakeCopy)
1808 { 1819 {
1809 // If we don't have permission, stop right here 1820 // If we don't have permission, stop right here
1810 if (!permissionToTakeCopy) 1821 if (!permissionToTakeCopy)
1811 return; 1822 return;
1812 1823
1813 permissionToTake = true; 1824 permissionToTake = true;
1814 // Don't delete 1825 // Don't delete
1815 permissionToDelete = false; 1826 permissionToDelete = false;
1816 } 1827 }
1817 1828
1818 if (action == DeRezAction.Return) 1829 if (action == DeRezAction.Return)
1819 {
1820 if (remoteClient != null)
1821 { 1830 {
1822 if (Permissions.CanReturnObjects( 1831 if (remoteClient != null)
1823 null,
1824 remoteClient.AgentId,
1825 deleteGroups))
1826 { 1832 {
1827 permissionToTake = true; 1833 if (Permissions.CanReturnObjects(
1828 permissionToDelete = true; 1834 null,
1829 1835 remoteClient.AgentId,
1830 foreach (SceneObjectGroup g in deleteGroups) 1836 deleteGroups))
1831 { 1837 {
1832 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1838 permissionToTake = true;
1839 permissionToDelete = true;
1840
1841 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1833 } 1842 }
1834 } 1843 }
1844 else // Auto return passes through here with null agent
1845 {
1846 permissionToTake = true;
1847 permissionToDelete = true;
1848 }
1835 } 1849 }
1836 else // Auto return passes through here with null agent 1850
1851 if (permissionToTake && (!permissionToDelete))
1852 takeGroups.Add(grp);
1853
1854 if (permissionToDelete)
1837 { 1855 {
1838 permissionToTake = true; 1856 if (permissionToTake)
1839 permissionToDelete = true; 1857 deleteGroups.Add(grp);
1858 deleteIDs.Add(grp.LocalId);
1840 } 1859 }
1841 } 1860 }
1842 1861
1843 if (permissionToTake) 1862 SendKillObject(deleteIDs);
1863
1864 if (deleteGroups.Count > 0)
1844 { 1865 {
1866 foreach (SceneObjectGroup g in deleteGroups)
1867 deleteIDs.Remove(g.LocalId);
1868
1845 m_asyncSceneObjectDeleter.DeleteToInventory( 1869 m_asyncSceneObjectDeleter.DeleteToInventory(
1846 action, destinationID, deleteGroups, remoteClient, 1870 action, destinationID, deleteGroups, remoteClient,
1847 permissionToDelete); 1871 true);
1872 }
1873 if (takeGroups.Count > 0)
1874 {
1875 m_asyncSceneObjectDeleter.DeleteToInventory(
1876 action, destinationID, takeGroups, remoteClient,
1877 false);
1848 } 1878 }
1849 else if (permissionToDelete) 1879 if (deleteIDs.Count > 0)
1850 { 1880 {
1851 foreach (SceneObjectGroup g in deleteGroups) 1881 foreach (SceneObjectGroup g in deleteGroups)
1852 DeleteSceneObject(g, false); 1882 DeleteSceneObject(g, true);
1853 } 1883 }
1854 } 1884 }
1855 1885
@@ -1901,21 +1931,29 @@ namespace OpenSim.Region.Framework.Scenes
1901 else // oopsies 1931 else // oopsies
1902 item.Folder = UUID.Zero; 1932 item.Folder = UUID.Zero;
1903 1933
1934 // Set up base perms properly
1935 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1936 permsBase &= grp.RootPart.BaseMask;
1937 permsBase |= (uint)PermissionMask.Move;
1938
1939 // Make sure we don't lock it
1940 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1941
1904 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions()) 1942 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1905 { 1943 {
1906 item.BasePermissions = grp.RootPart.NextOwnerMask; 1944 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1907 item.CurrentPermissions = grp.RootPart.NextOwnerMask; 1945 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1908 item.NextPermissions = grp.RootPart.NextOwnerMask; 1946 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1909 item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask; 1947 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1910 item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask; 1948 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1911 } 1949 }
1912 else 1950 else
1913 { 1951 {
1914 item.BasePermissions = grp.RootPart.BaseMask; 1952 item.BasePermissions = permsBase;
1915 item.CurrentPermissions = grp.RootPart.OwnerMask; 1953 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1916 item.NextPermissions = grp.RootPart.NextOwnerMask; 1954 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1917 item.EveryOnePermissions = grp.RootPart.EveryoneMask; 1955 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1918 item.GroupPermissions = grp.RootPart.GroupMask; 1956 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1919 } 1957 }
1920 item.CreationDate = Util.UnixTimeSinceEpoch(); 1958 item.CreationDate = Util.UnixTimeSinceEpoch();
1921 1959
@@ -2021,6 +2059,9 @@ namespace OpenSim.Region.Framework.Scenes
2021 2059
2022 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2060 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2023 { 2061 {
2062 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2063 return;
2064
2024 SceneObjectPart part = GetSceneObjectPart(objectID); 2065 SceneObjectPart part = GetSceneObjectPart(objectID);
2025 if (part == null) 2066 if (part == null)
2026 return; 2067 return;
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 355671c..171d637 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -86,6 +86,7 @@ namespace OpenSim.Region.Framework.Scenes
86 // TODO: need to figure out how allow client agents but deny 86 // TODO: need to figure out how allow client agents but deny
87 // root agents when ACL denies access to root agent 87 // root agents when ACL denies access to root agent
88 public bool m_strictAccessControl = true; 88 public bool m_strictAccessControl = true;
89 public bool m_seeIntoBannedRegion = false;
89 public int MaxUndoCount = 5; 90 public int MaxUndoCount = 5;
90 public bool LoginsDisabled = true; 91 public bool LoginsDisabled = true;
91 public bool LoadingPrims; 92 public bool LoadingPrims;
@@ -104,6 +105,7 @@ namespace OpenSim.Region.Framework.Scenes
104 protected ModuleLoader m_moduleLoader; 105 protected ModuleLoader m_moduleLoader;
105 protected AgentCircuitManager m_authenticateHandler; 106 protected AgentCircuitManager m_authenticateHandler;
106 protected SceneCommunicationService m_sceneGridService; 107 protected SceneCommunicationService m_sceneGridService;
108 protected ISnmpModule m_snmpService = null;
107 109
108 protected ISimulationDataService m_SimulationDataService; 110 protected ISimulationDataService m_SimulationDataService;
109 protected IEstateDataService m_EstateDataService; 111 protected IEstateDataService m_EstateDataService;
@@ -151,7 +153,7 @@ namespace OpenSim.Region.Framework.Scenes
151 private int m_update_events = 1; 153 private int m_update_events = 1;
152 private int m_update_backup = 200; 154 private int m_update_backup = 200;
153 private int m_update_terrain = 50; 155 private int m_update_terrain = 50;
154// private int m_update_land = 1; 156 private int m_update_land = 10;
155 private int m_update_coarse_locations = 50; 157 private int m_update_coarse_locations = 50;
156 158
157 private int frameMS; 159 private int frameMS;
@@ -165,6 +167,7 @@ namespace OpenSim.Region.Framework.Scenes
165 private int landMS; 167 private int landMS;
166 private int lastCompletedFrame; 168 private int lastCompletedFrame;
167 169
170 public bool CombineRegions = false;
168 private bool m_physics_enabled = true; 171 private bool m_physics_enabled = true;
169 private bool m_scripts_enabled = true; 172 private bool m_scripts_enabled = true;
170 private string m_defaultScriptEngine; 173 private string m_defaultScriptEngine;
@@ -173,6 +176,8 @@ namespace OpenSim.Region.Framework.Scenes
173 private volatile bool shuttingdown; 176 private volatile bool shuttingdown;
174 177
175 private int m_lastUpdate; 178 private int m_lastUpdate;
179 private int m_lastIncoming;
180 private int m_lastOutgoing;
176 private bool m_firstHeartbeat = true; 181 private bool m_firstHeartbeat = true;
177 182
178 private object m_deleting_scene_object = new object(); 183 private object m_deleting_scene_object = new object();
@@ -224,6 +229,19 @@ namespace OpenSim.Region.Framework.Scenes
224 get { return m_sceneGridService; } 229 get { return m_sceneGridService; }
225 } 230 }
226 231
232 public ISnmpModule SnmpService
233 {
234 get
235 {
236 if (m_snmpService == null)
237 {
238 m_snmpService = RequestModuleInterface<ISnmpModule>();
239 }
240
241 return m_snmpService;
242 }
243 }
244
227 public ISimulationDataService SimulationDataService 245 public ISimulationDataService SimulationDataService
228 { 246 {
229 get 247 get
@@ -549,6 +567,8 @@ namespace OpenSim.Region.Framework.Scenes
549 m_regionName = m_regInfo.RegionName; 567 m_regionName = m_regInfo.RegionName;
550 m_datastore = m_regInfo.DataStore; 568 m_datastore = m_regInfo.DataStore;
551 m_lastUpdate = Util.EnvironmentTickCount(); 569 m_lastUpdate = Util.EnvironmentTickCount();
570 m_lastIncoming = 0;
571 m_lastOutgoing = 0;
552 572
553 m_physicalPrim = physicalPrim; 573 m_physicalPrim = physicalPrim;
554 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor; 574 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
@@ -562,6 +582,8 @@ namespace OpenSim.Region.Framework.Scenes
562 #region Region Settings 582 #region Region Settings
563 583
564 // Load region settings 584 // Load region settings
585 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID);
586
565 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID); 587 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
566 if (estateDataService != null) 588 if (estateDataService != null)
567 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 589 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -621,9 +643,10 @@ namespace OpenSim.Region.Framework.Scenes
621 //Animation states 643 //Animation states
622 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 644 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
623 // TODO: Change default to true once the feature is supported 645 // TODO: Change default to true once the feature is supported
624 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 646 m_usePreJump = startupConfig.GetBoolean("enableprejump", true);
625
626 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 647 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
648
649 m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF");
627 if (RegionInfo.NonphysPrimMax > 0) 650 if (RegionInfo.NonphysPrimMax > 0)
628 { 651 {
629 m_maxNonphys = RegionInfo.NonphysPrimMax; 652 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -655,6 +678,7 @@ namespace OpenSim.Region.Framework.Scenes
655 m_persistAfter *= 10000000; 678 m_persistAfter *= 10000000;
656 679
657 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 680 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
681 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
658 682
659 IConfig packetConfig = m_config.Configs["PacketPool"]; 683 IConfig packetConfig = m_config.Configs["PacketPool"];
660 if (packetConfig != null) 684 if (packetConfig != null)
@@ -664,6 +688,8 @@ namespace OpenSim.Region.Framework.Scenes
664 } 688 }
665 689
666 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 690 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
691 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
692 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
667 693
668 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 694 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
669 if (m_generateMaptiles) 695 if (m_generateMaptiles)
@@ -688,9 +714,9 @@ namespace OpenSim.Region.Framework.Scenes
688 } 714 }
689 } 715 }
690 } 716 }
691 catch 717 catch (Exception e)
692 { 718 {
693 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 719 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
694 } 720 }
695 721
696 #endregion Region Config 722 #endregion Region Config
@@ -1061,7 +1087,9 @@ namespace OpenSim.Region.Framework.Scenes
1061 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1087 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1062 if (HeartbeatThread != null) 1088 if (HeartbeatThread != null)
1063 { 1089 {
1090 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1064 HeartbeatThread.Abort(); 1091 HeartbeatThread.Abort();
1092 Watchdog.RemoveThread(HeartbeatThread.ManagedThreadId);
1065 HeartbeatThread = null; 1093 HeartbeatThread = null;
1066 } 1094 }
1067 m_lastUpdate = Util.EnvironmentTickCount(); 1095 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1184,9 +1212,6 @@ namespace OpenSim.Region.Framework.Scenes
1184 try 1212 try
1185 { 1213 {
1186 Update(); 1214 Update();
1187
1188 m_lastUpdate = Util.EnvironmentTickCount();
1189 m_firstHeartbeat = false;
1190 } 1215 }
1191 catch (ThreadAbortException) 1216 catch (ThreadAbortException)
1192 { 1217 {
@@ -1301,12 +1326,12 @@ namespace OpenSim.Region.Framework.Scenes
1301 terrainMS = Util.EnvironmentTickCountSubtract(terMS); 1326 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1302 } 1327 }
1303 1328
1304 //if (m_frame % m_update_land == 0) 1329 if (m_frame % m_update_land == 0)
1305 //{ 1330 {
1306 // int ldMS = Util.EnvironmentTickCount(); 1331 int ldMS = Util.EnvironmentTickCount();
1307 // UpdateLand(); 1332 UpdateLand();
1308 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1333 landMS = Util.EnvironmentTickCountSubtract(ldMS);
1309 //} 1334 }
1310 1335
1311 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); 1336 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
1312 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1337 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
@@ -1377,6 +1402,9 @@ namespace OpenSim.Region.Framework.Scenes
1377 1402
1378 // Tell the watchdog that this thread is still alive 1403 // Tell the watchdog that this thread is still alive
1379 Watchdog.UpdateThread(); 1404 Watchdog.UpdateThread();
1405
1406 m_lastUpdate = Util.EnvironmentTickCount();
1407 m_firstHeartbeat = false;
1380 } 1408 }
1381 } 1409 }
1382 1410
@@ -1396,9 +1424,9 @@ namespace OpenSim.Region.Framework.Scenes
1396 1424
1397 private void CheckAtTargets() 1425 private void CheckAtTargets()
1398 { 1426 {
1399 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1427 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1400 lock (m_groupsWithTargets) 1428 lock (m_groupsWithTargets)
1401 objs = m_groupsWithTargets.Values; 1429 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1402 1430
1403 foreach (SceneObjectGroup entry in objs) 1431 foreach (SceneObjectGroup entry in objs)
1404 entry.checkAtTargets(); 1432 entry.checkAtTargets();
@@ -1732,14 +1760,24 @@ namespace OpenSim.Region.Framework.Scenes
1732 /// <returns></returns> 1760 /// <returns></returns>
1733 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1761 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1734 { 1762 {
1763
1764 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1765 Vector3 wpos = Vector3.Zero;
1766 // Check for water surface intersection from above
1767 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1768 {
1769 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1770 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1771 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1772 wpos.Z = wheight;
1773 }
1774
1735 Vector3 pos = Vector3.Zero; 1775 Vector3 pos = Vector3.Zero;
1736 if (RayEndIsIntersection == (byte)1) 1776 if (RayEndIsIntersection == (byte)1)
1737 { 1777 {
1738 pos = RayEnd; 1778 pos = RayEnd;
1739 return pos;
1740 } 1779 }
1741 1780 else if (RayTargetID != UUID.Zero)
1742 if (RayTargetID != UUID.Zero)
1743 { 1781 {
1744 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1782 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1745 1783
@@ -1761,7 +1799,7 @@ namespace OpenSim.Region.Framework.Scenes
1761 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1799 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1762 1800
1763 // Un-comment out the following line to Get Raytrace results printed to the console. 1801 // Un-comment out the following line to Get Raytrace results printed to the console.
1764 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1802 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1765 float ScaleOffset = 0.5f; 1803 float ScaleOffset = 0.5f;
1766 1804
1767 // If we hit something 1805 // If we hit something
@@ -1784,13 +1822,10 @@ namespace OpenSim.Region.Framework.Scenes
1784 //pos.Z -= 0.25F; 1822 //pos.Z -= 0.25F;
1785 1823
1786 } 1824 }
1787
1788 return pos;
1789 } 1825 }
1790 else 1826 else
1791 { 1827 {
1792 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1828 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1793
1794 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1829 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1795 1830
1796 // Un-comment the following line to print the raytrace results to the console. 1831 // Un-comment the following line to print the raytrace results to the console.
@@ -1799,13 +1834,12 @@ namespace OpenSim.Region.Framework.Scenes
1799 if (ei.HitTF) 1834 if (ei.HitTF)
1800 { 1835 {
1801 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1836 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1802 } else 1837 }
1838 else
1803 { 1839 {
1804 // fall back to our stupid functionality 1840 // fall back to our stupid functionality
1805 pos = RayEnd; 1841 pos = RayEnd;
1806 } 1842 }
1807
1808 return pos;
1809 } 1843 }
1810 } 1844 }
1811 else 1845 else
@@ -1816,8 +1850,12 @@ namespace OpenSim.Region.Framework.Scenes
1816 //increase height so its above the ground. 1850 //increase height so its above the ground.
1817 //should be getting the normal of the ground at the rez point and using that? 1851 //should be getting the normal of the ground at the rez point and using that?
1818 pos.Z += scale.Z / 2f; 1852 pos.Z += scale.Z / 2f;
1819 return pos; 1853// return pos;
1820 } 1854 }
1855
1856 // check against posible water intercept
1857 if (wpos.Z > pos.Z) pos = wpos;
1858 return pos;
1821 } 1859 }
1822 1860
1823 1861
@@ -1897,7 +1935,10 @@ namespace OpenSim.Region.Framework.Scenes
1897 public bool AddRestoredSceneObject( 1935 public bool AddRestoredSceneObject(
1898 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1936 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1899 { 1937 {
1900 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1938 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1939 if (result)
1940 sceneObject.IsDeleted = false;
1941 return result;
1901 } 1942 }
1902 1943
1903 /// <summary> 1944 /// <summary>
@@ -1974,6 +2015,15 @@ namespace OpenSim.Region.Framework.Scenes
1974 /// </summary> 2015 /// </summary>
1975 public void DeleteAllSceneObjects() 2016 public void DeleteAllSceneObjects()
1976 { 2017 {
2018 DeleteAllSceneObjects(false);
2019 }
2020
2021 /// <summary>
2022 /// Delete every object from the scene. This does not include attachments worn by avatars.
2023 /// </summary>
2024 public void DeleteAllSceneObjects(bool exceptNoCopy)
2025 {
2026 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1977 lock (Entities) 2027 lock (Entities)
1978 { 2028 {
1979 EntityBase[] entities = Entities.GetEntities(); 2029 EntityBase[] entities = Entities.GetEntities();
@@ -1982,11 +2032,24 @@ namespace OpenSim.Region.Framework.Scenes
1982 if (e is SceneObjectGroup) 2032 if (e is SceneObjectGroup)
1983 { 2033 {
1984 SceneObjectGroup sog = (SceneObjectGroup)e; 2034 SceneObjectGroup sog = (SceneObjectGroup)e;
1985 if (!sog.IsAttachment) 2035 if (sog != null && !sog.IsAttachment)
1986 DeleteSceneObject((SceneObjectGroup)e, false); 2036 {
2037 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2038 {
2039 DeleteSceneObject((SceneObjectGroup)e, false);
2040 }
2041 else
2042 {
2043 toReturn.Add((SceneObjectGroup)e);
2044 }
2045 }
1987 } 2046 }
1988 } 2047 }
1989 } 2048 }
2049 if (toReturn.Count > 0)
2050 {
2051 returnObjects(toReturn.ToArray(), UUID.Zero);
2052 }
1990 } 2053 }
1991 2054
1992 /// <summary> 2055 /// <summary>
@@ -2035,6 +2098,8 @@ namespace OpenSim.Region.Framework.Scenes
2035 } 2098 }
2036 2099
2037 group.DeleteGroupFromScene(silent); 2100 group.DeleteGroupFromScene(silent);
2101 if (!silent)
2102 SendKillObject(new List<uint>() { group.LocalId });
2038 2103
2039// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2104// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2040 } 2105 }
@@ -2365,10 +2430,17 @@ namespace OpenSim.Region.Framework.Scenes
2365 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2430 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2366 public bool AddSceneObject(SceneObjectGroup sceneObject) 2431 public bool AddSceneObject(SceneObjectGroup sceneObject)
2367 { 2432 {
2433 if (sceneObject.OwnerID == UUID.Zero)
2434 {
2435 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2436 return false;
2437 }
2438
2368 // If the user is banned, we won't let any of their objects 2439 // If the user is banned, we won't let any of their objects
2369 // enter. Period. 2440 // enter. Period.
2370 // 2441 //
2371 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2442 int flags = GetUserFlags(sceneObject.OwnerID);
2443 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2372 { 2444 {
2373 m_log.Info("[INTERREGION]: Denied prim crossing for " + 2445 m_log.Info("[INTERREGION]: Denied prim crossing for " +
2374 "banned avatar"); 2446 "banned avatar");
@@ -2412,15 +2484,28 @@ namespace OpenSim.Region.Framework.Scenes
2412 2484
2413 if (AttachmentsModule != null) 2485 if (AttachmentsModule != null)
2414 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2486 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2487
2488 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2415 } 2489 }
2416 else 2490 else
2417 { 2491 {
2492 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2418 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2493 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2419 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2494 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2420 } 2495 }
2496 if (sceneObject.OwnerID == UUID.Zero)
2497 {
2498 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2499 return false;
2500 }
2421 } 2501 }
2422 else 2502 else
2423 { 2503 {
2504 if (sceneObject.OwnerID == UUID.Zero)
2505 {
2506 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2507 return false;
2508 }
2424 AddRestoredSceneObject(sceneObject, true, false); 2509 AddRestoredSceneObject(sceneObject, true, false);
2425 2510
2426 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2511 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2459,6 +2544,24 @@ namespace OpenSim.Region.Framework.Scenes
2459 return 2; // StateSource.PrimCrossing 2544 return 2; // StateSource.PrimCrossing
2460 } 2545 }
2461 2546
2547 public int GetUserFlags(UUID user)
2548 {
2549 //Unfortunately the SP approach means that the value is cached until region is restarted
2550 /*
2551 ScenePresence sp;
2552 if (TryGetScenePresence(user, out sp))
2553 {
2554 return sp.UserFlags;
2555 }
2556 else
2557 {
2558 */
2559 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2560 if (uac == null)
2561 return 0;
2562 return uac.UserFlags;
2563 //}
2564 }
2462 #endregion 2565 #endregion
2463 2566
2464 #region Add/Remove Avatar Methods 2567 #region Add/Remove Avatar Methods
@@ -2479,6 +2582,7 @@ namespace OpenSim.Region.Framework.Scenes
2479 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2582 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2480 2583
2481 CheckHeartbeat(); 2584 CheckHeartbeat();
2585 ScenePresence presence;
2482 2586
2483 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here 2587 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here
2484 { 2588 {
@@ -2502,12 +2606,19 @@ namespace OpenSim.Region.Framework.Scenes
2502 } 2606 }
2503 } 2607 }
2504 2608
2505 if (GetScenePresence(client.AgentId) != null) 2609 if (TryGetScenePresence(client.AgentId, out presence))
2506 { 2610 {
2507 m_LastLogin = Util.EnvironmentTickCount(); 2611 m_LastLogin = Util.EnvironmentTickCount();
2508 EventManager.TriggerOnNewClient(client); 2612 EventManager.TriggerOnNewClient(client);
2509 if (vialogin) 2613 if (vialogin)
2614 {
2510 EventManager.TriggerOnClientLogin(client); 2615 EventManager.TriggerOnClientLogin(client);
2616
2617 // Send initial parcel data
2618 Vector3 pos = presence.AbsolutePosition;
2619 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2620 land.SendLandUpdateToClient(presence.ControllingClient);
2621 }
2511 } 2622 }
2512 } 2623 }
2513 2624
@@ -2558,19 +2669,12 @@ namespace OpenSim.Region.Framework.Scenes
2558 // and the scene presence and the client, if they exist 2669 // and the scene presence and the client, if they exist
2559 try 2670 try
2560 { 2671 {
2561 // We need to wait for the client to make UDP contact first. 2672 ScenePresence sp = GetScenePresence(agentID);
2562 // It's the UDP contact that creates the scene presence 2673 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2563 ScenePresence sp = WaitGetScenePresence(agentID); 2674
2564 if (sp != null) 2675 if (sp != null)
2565 {
2566 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2567
2568 sp.ControllingClient.Close(); 2676 sp.ControllingClient.Close();
2569 } 2677
2570 else
2571 {
2572 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2573 }
2574 // BANG! SLASH! 2678 // BANG! SLASH!
2575 m_authenticateHandler.RemoveCircuit(agentID); 2679 m_authenticateHandler.RemoveCircuit(agentID);
2576 2680
@@ -2670,6 +2774,7 @@ namespace OpenSim.Region.Framework.Scenes
2670 client.OnFetchInventory += HandleFetchInventory; 2774 client.OnFetchInventory += HandleFetchInventory;
2671 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2775 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2672 client.OnCopyInventoryItem += CopyInventoryItem; 2776 client.OnCopyInventoryItem += CopyInventoryItem;
2777 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2673 client.OnMoveInventoryItem += MoveInventoryItem; 2778 client.OnMoveInventoryItem += MoveInventoryItem;
2674 client.OnRemoveInventoryItem += RemoveInventoryItem; 2779 client.OnRemoveInventoryItem += RemoveInventoryItem;
2675 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2780 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2848,15 +2953,16 @@ namespace OpenSim.Region.Framework.Scenes
2848 /// </summary> 2953 /// </summary>
2849 /// <param name="agentId">The avatar's Unique ID</param> 2954 /// <param name="agentId">The avatar's Unique ID</param>
2850 /// <param name="client">The IClientAPI for the client</param> 2955 /// <param name="client">The IClientAPI for the client</param>
2851 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 2956 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2852 { 2957 {
2853 if (m_teleportModule != null) 2958 if (m_teleportModule != null)
2854 m_teleportModule.TeleportHome(agentId, client); 2959 return m_teleportModule.TeleportHome(agentId, client);
2855 else 2960 else
2856 { 2961 {
2857 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 2962 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2858 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 2963 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2859 } 2964 }
2965 return false;
2860 } 2966 }
2861 2967
2862 /// <summary> 2968 /// <summary>
@@ -2955,6 +3061,16 @@ namespace OpenSim.Region.Framework.Scenes
2955 /// <param name="flags"></param> 3061 /// <param name="flags"></param>
2956 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3062 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
2957 { 3063 {
3064 //Add half the avatar's height so that the user doesn't fall through prims
3065 ScenePresence presence;
3066 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3067 {
3068 if (presence.Appearance != null)
3069 {
3070 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3071 }
3072 }
3073
2958 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3074 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
2959 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3075 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
2960 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3076 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3029,7 +3145,9 @@ namespace OpenSim.Region.Framework.Scenes
3029 regions.Remove(RegionInfo.RegionHandle); 3145 regions.Remove(RegionInfo.RegionHandle);
3030 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3146 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3031 } 3147 }
3148 m_log.Debug("[Scene] Beginning ClientClosed");
3032 m_eventManager.TriggerClientClosed(agentID, this); 3149 m_eventManager.TriggerClientClosed(agentID, this);
3150 m_log.Debug("[Scene] Finished ClientClosed");
3033 } 3151 }
3034 catch (NullReferenceException) 3152 catch (NullReferenceException)
3035 { 3153 {
@@ -3037,7 +3155,12 @@ namespace OpenSim.Region.Framework.Scenes
3037 // Avatar is already disposed :/ 3155 // Avatar is already disposed :/
3038 } 3156 }
3039 3157
3158 m_log.Debug("[Scene] Beginning OnRemovePresence");
3040 m_eventManager.TriggerOnRemovePresence(agentID); 3159 m_eventManager.TriggerOnRemovePresence(agentID);
3160 m_log.Debug("[Scene] Finished OnRemovePresence");
3161
3162 if (avatar != null && (!avatar.IsChildAgent))
3163 avatar.SaveChangedAttachments();
3041 3164
3042 if (avatar != null && (!avatar.IsChildAgent)) 3165 if (avatar != null && (!avatar.IsChildAgent))
3043 avatar.SaveChangedAttachments(); 3166 avatar.SaveChangedAttachments();
@@ -3046,7 +3169,7 @@ namespace OpenSim.Region.Framework.Scenes
3046 delegate(IClientAPI client) 3169 delegate(IClientAPI client)
3047 { 3170 {
3048 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3171 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3049 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3172 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3050 catch (NullReferenceException) { } 3173 catch (NullReferenceException) { }
3051 }); 3174 });
3052 3175
@@ -3057,8 +3180,11 @@ namespace OpenSim.Region.Framework.Scenes
3057 } 3180 }
3058 3181
3059 // Remove the avatar from the scene 3182 // Remove the avatar from the scene
3183 m_log.Debug("[Scene] Begin RemoveScenePresence");
3060 m_sceneGraph.RemoveScenePresence(agentID); 3184 m_sceneGraph.RemoveScenePresence(agentID);
3185 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3061 m_clientManager.Remove(agentID); 3186 m_clientManager.Remove(agentID);
3187 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3062 3188
3063 try 3189 try
3064 { 3190 {
@@ -3072,9 +3198,10 @@ namespace OpenSim.Region.Framework.Scenes
3072 { 3198 {
3073 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3199 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3074 } 3200 }
3075 3201 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3076 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3202 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3077 CleanDroppedAttachments(); 3203 CleanDroppedAttachments();
3204 m_log.Debug("[Scene] The avatar has left the building");
3078 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3205 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3079 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3206 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3080 } 3207 }
@@ -3105,18 +3232,24 @@ namespace OpenSim.Region.Framework.Scenes
3105 3232
3106 #region Entities 3233 #region Entities
3107 3234
3108 public void SendKillObject(uint localID) 3235 public void SendKillObject(List<uint> localIDs)
3109 { 3236 {
3110 SceneObjectPart part = GetSceneObjectPart(localID); 3237 List<uint> deleteIDs = new List<uint>();
3111 if (part != null) // It is a prim 3238
3239 foreach (uint localID in localIDs)
3112 { 3240 {
3113 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3241 SceneObjectPart part = GetSceneObjectPart(localID);
3242 if (part != null) // It is a prim
3114 { 3243 {
3115 if (part.ParentGroup.RootPart != part) // Child part 3244 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3116 return; 3245 {
3246 if (part.ParentGroup.RootPart != part) // Child part
3247 continue;
3248 }
3117 } 3249 }
3250 deleteIDs.Add(localID);
3118 } 3251 }
3119 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); 3252 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3120 } 3253 }
3121 3254
3122 #endregion 3255 #endregion
@@ -3134,7 +3267,6 @@ namespace OpenSim.Region.Framework.Scenes
3134 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3267 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3135 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3268 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3136 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3269 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3137 m_sceneGridService.KiPrimitive += SendKillObject;
3138 m_sceneGridService.OnGetLandData += GetLandData; 3270 m_sceneGridService.OnGetLandData += GetLandData;
3139 } 3271 }
3140 3272
@@ -3143,7 +3275,6 @@ namespace OpenSim.Region.Framework.Scenes
3143 /// </summary> 3275 /// </summary>
3144 public void UnRegisterRegionWithComms() 3276 public void UnRegisterRegionWithComms()
3145 { 3277 {
3146 m_sceneGridService.KiPrimitive -= SendKillObject;
3147 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3278 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3148 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3279 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3149 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3280 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3223,13 +3354,16 @@ namespace OpenSim.Region.Framework.Scenes
3223 sp = null; 3354 sp = null;
3224 } 3355 }
3225 3356
3226 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3227 3357
3228 //On login test land permisions 3358 //On login test land permisions
3229 if (vialogin) 3359 if (vialogin)
3230 { 3360 {
3231 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3361 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3362 if (cache != null)
3363 cache.Remove(agent.firstname + " " + agent.lastname);
3364 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3232 { 3365 {
3366 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3233 return false; 3367 return false;
3234 } 3368 }
3235 } 3369 }
@@ -3252,8 +3386,13 @@ namespace OpenSim.Region.Framework.Scenes
3252 3386
3253 try 3387 try
3254 { 3388 {
3255 if (!AuthorizeUser(agent, out reason)) 3389 // Always check estate if this is a login. Always
3256 return false; 3390 // check if banned regions are to be blacked out.
3391 if (vialogin || (!m_seeIntoBannedRegion))
3392 {
3393 if (!AuthorizeUser(agent.AgentID, out reason))
3394 return false;
3395 }
3257 } 3396 }
3258 catch (Exception e) 3397 catch (Exception e)
3259 { 3398 {
@@ -3351,6 +3490,8 @@ namespace OpenSim.Region.Framework.Scenes
3351 } 3490 }
3352 } 3491 }
3353 // Honor parcel landing type and position. 3492 // Honor parcel landing type and position.
3493 /*
3494 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3354 if (land != null) 3495 if (land != null)
3355 { 3496 {
3356 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3497 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3358,26 +3499,32 @@ namespace OpenSim.Region.Framework.Scenes
3358 agent.startpos = land.LandData.UserLocation; 3499 agent.startpos = land.LandData.UserLocation;
3359 } 3500 }
3360 } 3501 }
3502 */// This is now handled properly in ScenePresence.MakeRootAgent
3361 } 3503 }
3362 3504
3363 return true; 3505 return true;
3364 } 3506 }
3365 3507
3366 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3508 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3367 { 3509 {
3368 3510 reason = String.Empty;
3369 bool banned = land.IsBannedFromLand(agent.AgentID); 3511
3370 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3512 ILandObject land = LandChannel.GetLandObject(posX, posY);
3513 if (land == null)
3514 return false;
3515
3516 bool banned = land.IsBannedFromLand(agentID);
3517 bool restricted = land.IsRestrictedFromLand(agentID);
3371 3518
3372 if (banned || restricted) 3519 if (banned || restricted)
3373 { 3520 {
3374 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3521 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3375 if (nearestParcel != null) 3522 if (nearestParcel != null)
3376 { 3523 {
3377 //Move agent to nearest allowed 3524 //Move agent to nearest allowed
3378 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3525 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3379 agent.startpos.X = newPosition.X; 3526 posX = newPosition.X;
3380 agent.startpos.Y = newPosition.Y; 3527 posY = newPosition.Y;
3381 } 3528 }
3382 else 3529 else
3383 { 3530 {
@@ -3433,19 +3580,19 @@ namespace OpenSim.Region.Framework.Scenes
3433 /// <param name="reason">outputs the reason to this string</param> 3580 /// <param name="reason">outputs the reason to this string</param>
3434 /// <returns>True if the region accepts this agent. False if it does not. False will 3581 /// <returns>True if the region accepts this agent. False if it does not. False will
3435 /// also return a reason.</returns> 3582 /// also return a reason.</returns>
3436 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 3583 protected virtual bool AuthorizeUser(UUID agentID, out string reason)
3437 { 3584 {
3438 reason = String.Empty; 3585 reason = String.Empty;
3439 3586
3440 if (!m_strictAccessControl) return true; 3587 if (!m_strictAccessControl) return true;
3441 if (Permissions.IsGod(agent.AgentID)) return true; 3588 if (Permissions.IsGod(agentID)) return true;
3442 3589
3443 if (AuthorizationService != null) 3590 if (AuthorizationService != null)
3444 { 3591 {
3445 if (!AuthorizationService.IsAuthorizedForRegion(agent.AgentID.ToString(), RegionInfo.RegionID.ToString(),out reason)) 3592 if (!AuthorizationService.IsAuthorizedForRegion(agentID.ToString(), RegionInfo.RegionID.ToString(),out reason))
3446 { 3593 {
3447 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3594 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the region",
3448 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3595 agentID, RegionInfo.RegionName);
3449 //reason = String.Format("You are not currently on the access list for {0}",RegionInfo.RegionName); 3596 //reason = String.Format("You are not currently on the access list for {0}",RegionInfo.RegionName);
3450 return false; 3597 return false;
3451 } 3598 }
@@ -3453,10 +3600,26 @@ namespace OpenSim.Region.Framework.Scenes
3453 3600
3454 if (m_regInfo.EstateSettings != null) 3601 if (m_regInfo.EstateSettings != null)
3455 { 3602 {
3456 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3603 int flags = GetUserFlags(agentID);
3604 if (m_regInfo.EstateSettings.IsBanned(agentID, flags))
3457 { 3605 {
3458 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3606 //Add some more info to help users
3459 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3607 if (!m_regInfo.EstateSettings.IsBanned(agentID, 32))
3608 {
3609 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the region requires age verification",
3610 agentID, RegionInfo.RegionName);
3611 reason = String.Format("Denied access to region {0}: Region requires age verification", RegionInfo.RegionName);
3612 return false;
3613 }
3614 if (!m_regInfo.EstateSettings.IsBanned(agentID, 4))
3615 {
3616 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} {1} because the region requires payment info on file",
3617 agentID, RegionInfo.RegionName);
3618 reason = String.Format("Denied access to region {0}: Region requires payment info on file", RegionInfo.RegionName);
3619 return false;
3620 }
3621 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {3} because the user is on the banlist",
3622 agentID, RegionInfo.RegionName);
3460 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 3623 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
3461 RegionInfo.RegionName); 3624 RegionInfo.RegionName);
3462 return false; 3625 return false;
@@ -3473,7 +3636,7 @@ namespace OpenSim.Region.Framework.Scenes
3473 if (groupsModule != null) 3636 if (groupsModule != null)
3474 { 3637 {
3475 GroupMembershipData[] GroupMembership = 3638 GroupMembershipData[] GroupMembership =
3476 groupsModule.GetMembershipData(agent.AgentID); 3639 groupsModule.GetMembershipData(agentID);
3477 3640
3478 if (GroupMembership != null) 3641 if (GroupMembership != null)
3479 { 3642 {
@@ -3502,44 +3665,16 @@ namespace OpenSim.Region.Framework.Scenes
3502 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 3665 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
3503 3666
3504 if (!m_regInfo.EstateSettings.PublicAccess && 3667 if (!m_regInfo.EstateSettings.PublicAccess &&
3505 !m_regInfo.EstateSettings.HasAccess(agent.AgentID) && 3668 !m_regInfo.EstateSettings.HasAccess(agentID) &&
3506 !groupAccess) 3669 !groupAccess)
3507 { 3670 {
3508 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 3671 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the estate",
3509 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3672 agentID, RegionInfo.RegionName);
3510 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 3673 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3511 RegionInfo.RegionName); 3674 RegionInfo.RegionName);
3512 return false; 3675 return false;
3513 } 3676 }
3514 3677
3515 // TODO: estate/region settings are not properly hooked up
3516 // to ILandObject.isRestrictedFromLand()
3517 // if (null != LandChannel)
3518 // {
3519 // // region seems to have local Id of 1
3520 // ILandObject land = LandChannel.GetLandObject(1);
3521 // if (null != land)
3522 // {
3523 // if (land.isBannedFromLand(agent.AgentID))
3524 // {
3525 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land",
3526 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3527 // reason = String.Format("Denied access to private region {0}: You are banned from that region.",
3528 // RegionInfo.RegionName);
3529 // return false;
3530 // }
3531
3532 // if (land.isRestrictedFromLand(agent.AgentID))
3533 // {
3534 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3535 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3536 // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3537 // RegionInfo.RegionName);
3538 // return false;
3539 // }
3540 // }
3541 // }
3542
3543 return true; 3678 return true;
3544 } 3679 }
3545 3680
@@ -3643,6 +3778,13 @@ namespace OpenSim.Region.Framework.Scenes
3643 3778
3644 // We have to wait until the viewer contacts this region after receiving EAC. 3779 // We have to wait until the viewer contacts this region after receiving EAC.
3645 // That calls AddNewClient, which finally creates the ScenePresence 3780 // That calls AddNewClient, which finally creates the ScenePresence
3781 int flags = GetUserFlags(cAgentData.AgentID);
3782 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3783 {
3784 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3785 return false;
3786 }
3787
3646 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3788 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3647 if (nearestParcel == null) 3789 if (nearestParcel == null)
3648 { 3790 {
@@ -3650,6 +3792,14 @@ namespace OpenSim.Region.Framework.Scenes
3650 return false; 3792 return false;
3651 } 3793 }
3652 3794
3795 int num = m_sceneGraph.GetNumberOfScenePresences();
3796
3797 if (num >= RegionInfo.RegionSettings.AgentLimit)
3798 {
3799 if (!Permissions.IsAdministrator(cAgentData.AgentID))
3800 return false;
3801 }
3802
3653 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3803 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3654 3804
3655 if (childAgentUpdate != null) 3805 if (childAgentUpdate != null)
@@ -3716,12 +3866,22 @@ namespace OpenSim.Region.Framework.Scenes
3716 return false; 3866 return false;
3717 } 3867 }
3718 3868
3869 public bool IncomingCloseAgent(UUID agentID)
3870 {
3871 return IncomingCloseAgent(agentID, false);
3872 }
3873
3874 public bool IncomingCloseChildAgent(UUID agentID)
3875 {
3876 return IncomingCloseAgent(agentID, true);
3877 }
3878
3719 /// <summary> 3879 /// <summary>
3720 /// Tell a single agent to disconnect from the region. 3880 /// Tell a single agent to disconnect from the region.
3721 /// </summary> 3881 /// </summary>
3722 /// <param name="regionHandle"></param>
3723 /// <param name="agentID"></param> 3882 /// <param name="agentID"></param>
3724 public bool IncomingCloseAgent(UUID agentID) 3883 /// <param name="childOnly"></param>
3884 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3725 { 3885 {
3726 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3886 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3727 3887
@@ -3733,7 +3893,7 @@ namespace OpenSim.Region.Framework.Scenes
3733 { 3893 {
3734 m_sceneGraph.removeUserCount(false); 3894 m_sceneGraph.removeUserCount(false);
3735 } 3895 }
3736 else 3896 else if (!childOnly)
3737 { 3897 {
3738 m_sceneGraph.removeUserCount(true); 3898 m_sceneGraph.removeUserCount(true);
3739 } 3899 }
@@ -3749,9 +3909,12 @@ namespace OpenSim.Region.Framework.Scenes
3749 } 3909 }
3750 else 3910 else
3751 presence.ControllingClient.SendShutdownConnectionNotice(); 3911 presence.ControllingClient.SendShutdownConnectionNotice();
3912 presence.ControllingClient.Close(false);
3913 }
3914 else if (!childOnly)
3915 {
3916 presence.ControllingClient.Close(true);
3752 } 3917 }
3753
3754 presence.ControllingClient.Close();
3755 return true; 3918 return true;
3756 } 3919 }
3757 3920
@@ -4361,34 +4524,66 @@ namespace OpenSim.Region.Framework.Scenes
4361 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4524 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4362 } 4525 }
4363 4526
4364 public int GetHealth() 4527 public int GetHealth(out int flags, out string message)
4365 { 4528 {
4366 // Returns: 4529 // Returns:
4367 // 1 = sim is up and accepting http requests. The heartbeat has 4530 // 1 = sim is up and accepting http requests. The heartbeat has
4368 // stopped and the sim is probably locked up, but a remote 4531 // stopped and the sim is probably locked up, but a remote
4369 // admin restart may succeed 4532 // admin restart may succeed
4370 // 4533 //
4371 // 2 = Sim is up and the heartbeat is running. The sim is likely 4534 // 2 = Sim is up and the heartbeat is running. The sim is likely
4372 // usable for people within and logins _may_ work 4535 // usable for people within
4536 //
4537 // 3 = Sim is up and one packet thread is running. Sim is
4538 // unstable and will not accept new logins
4373 // 4539 //
4374 // 3 = We have seen a new user enter within the past 4 minutes 4540 // 4 = Sim is up and both packet threads are running. Sim is
4541 // likely usable
4542 //
4543 // 5 = We have seen a new user enter within the past 4 minutes
4375 // which can be seen as positive confirmation of sim health 4544 // which can be seen as positive confirmation of sim health
4376 // 4545 //
4546
4547 flags = 0;
4548 message = String.Empty;
4549
4550 CheckHeartbeat();
4551
4552 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4553 {
4554 // We're still starting
4555 // 0 means "in startup", it can't happen another way, since
4556 // to get here, we must be able to accept http connections
4557 return 0;
4558 }
4559
4377 int health=1; // Start at 1, means we're up 4560 int health=1; // Start at 1, means we're up
4378 4561
4379 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4562 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4563 {
4380 health+=1; 4564 health+=1;
4381 else 4565 flags |= 1;
4566 }
4567
4568 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4569 {
4570 health+=1;
4571 flags |= 2;
4572 }
4573
4574 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4575 {
4576 health+=1;
4577 flags |= 4;
4578 }
4579
4580 if (flags != 7)
4382 return health; 4581 return health;
4383 4582
4384 // A login in the last 4 mins? We can't be doing too badly 4583 // A login in the last 4 mins? We can't be doing too badly
4385 // 4584 //
4386 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4585 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4387 health++; 4586 health++;
4388 else
4389 return health;
4390
4391 CheckHeartbeat();
4392 4587
4393 return health; 4588 return health;
4394 } 4589 }
@@ -4581,7 +4776,7 @@ namespace OpenSim.Region.Framework.Scenes
4581 if (m_firstHeartbeat) 4776 if (m_firstHeartbeat)
4582 return; 4777 return;
4583 4778
4584 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4779 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 10000)
4585 StartTimer(); 4780 StartTimer();
4586 } 4781 }
4587 4782
@@ -4839,8 +5034,17 @@ namespace OpenSim.Region.Framework.Scenes
4839 { 5034 {
4840 float ominX, ominY, ominZ, omaxX, omaxY, omaxZ; 5035 float ominX, ominY, ominZ, omaxX, omaxY, omaxZ;
4841 5036
5037 Vector3 vec = g.AbsolutePosition;
5038
4842 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ); 5039 g.GetAxisAlignedBoundingBoxRaw(out ominX, out omaxX, out ominY, out omaxY, out ominZ, out omaxZ);
4843 5040
5041 ominX += vec.X;
5042 omaxX += vec.X;
5043 ominY += vec.Y;
5044 omaxY += vec.Y;
5045 ominZ += vec.Z;
5046 omaxZ += vec.Z;
5047
4844 if (minX > ominX) 5048 if (minX > ominX)
4845 minX = ominX; 5049 minX = ominX;
4846 if (minY > ominY) 5050 if (minY > ominY)
@@ -4910,10 +5114,28 @@ namespace OpenSim.Region.Framework.Scenes
4910 }); 5114 });
4911 } 5115 }
4912 5116
4913 foreach (SceneObjectGroup grp in objectsToDelete) 5117 if (objectsToDelete.Count > 0)
4914 { 5118 {
4915 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); 5119 m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count);
4916 DeleteSceneObject(grp, true); 5120 foreach (SceneObjectGroup grp in objectsToDelete)
5121 {
5122 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5123 DeleteSceneObject(grp, true);
5124 }
5125 m_log.Debug("[SCENE]: Finished dropped attachment deletion");
5126 }
5127 }
5128
5129 public void ThreadAlive(int threadCode)
5130 {
5131 switch(threadCode)
5132 {
5133 case 1: // Incoming
5134 m_lastIncoming = Util.EnvironmentTickCount();
5135 break;
5136 case 2: // Incoming
5137 m_lastOutgoing = Util.EnvironmentTickCount();
5138 break;
4917 } 5139 }
4918 } 5140 }
4919 5141
@@ -4925,6 +5147,37 @@ namespace OpenSim.Region.Framework.Scenes
4925 // child agent creation, thereby emulating the SL behavior. 5147 // child agent creation, thereby emulating the SL behavior.
4926 public bool QueryAccess(UUID agentID, Vector3 position) 5148 public bool QueryAccess(UUID agentID, Vector3 position)
4927 { 5149 {
5150 string reason;
5151
5152 if (!AuthorizeUser(agentID, out reason))
5153 {
5154 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5155 return false;
5156 }
5157
5158 if (position == Vector3.Zero) // Teleport
5159 {
5160 float posX = 128.0f;
5161 float posY = 128.0f;
5162
5163 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5164 {
5165 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5166 return false;
5167 }
5168 }
5169 else // Walking
5170 {
5171 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5172 if (land == null)
5173 return false;
5174
5175 bool banned = land.IsBannedFromLand(agentID);
5176 bool restricted = land.IsRestrictedFromLand(agentID);
5177
5178 if (banned || restricted)
5179 return false;
5180 }
4928 return true; 5181 return true;
4929 } 5182 }
4930 } 5183 }
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 969ff13..92fe2ab 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
@@ -123,13 +132,18 @@ namespace OpenSim.Region.Framework.Scenes
123 132
124 protected internal void Close() 133 protected internal void Close()
125 { 134 {
126 lock (m_presenceLock) 135 m_scenePresencesLock.EnterWriteLock();
136 try
127 { 137 {
128 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 138 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
129 List<ScenePresence> newlist = new List<ScenePresence>(); 139 List<ScenePresence> newlist = new List<ScenePresence>();
130 m_scenePresenceMap = newmap; 140 m_scenePresenceMap = newmap;
131 m_scenePresenceArray = newlist; 141 m_scenePresenceArray = newlist;
132 } 142 }
143 finally
144 {
145 m_scenePresencesLock.ExitWriteLock();
146 }
133 147
134 lock (SceneObjectGroupsByFullID) 148 lock (SceneObjectGroupsByFullID)
135 SceneObjectGroupsByFullID.Clear(); 149 SceneObjectGroupsByFullID.Clear();
@@ -258,6 +272,33 @@ namespace OpenSim.Region.Framework.Scenes
258 protected internal bool AddRestoredSceneObject( 272 protected internal bool AddRestoredSceneObject(
259 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 273 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
260 { 274 {
275 if (!m_parentScene.CombineRegions)
276 {
277 // KF: Check for out-of-region, move inside and make static.
278 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
279 sceneObject.RootPart.GroupPosition.Y,
280 sceneObject.RootPart.GroupPosition.Z);
281 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 ||
282 npos.X > Constants.RegionSize ||
283 npos.Y > Constants.RegionSize))
284 {
285 if (npos.X < 0.0) npos.X = 1.0f;
286 if (npos.Y < 0.0) npos.Y = 1.0f;
287 if (npos.Z < 0.0) npos.Z = 0.0f;
288 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
289 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
290
291 foreach (SceneObjectPart part in sceneObject.Parts)
292 {
293 part.GroupPosition = npos;
294 }
295 sceneObject.RootPart.Velocity = Vector3.Zero;
296 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
297 sceneObject.RootPart.Acceleration = Vector3.Zero;
298 sceneObject.RootPart.Velocity = Vector3.Zero;
299 }
300 }
301
261 if (attachToBackup && (!alreadyPersisted)) 302 if (attachToBackup && (!alreadyPersisted))
262 { 303 {
263 sceneObject.ForceInventoryPersistence(); 304 sceneObject.ForceInventoryPersistence();
@@ -457,6 +498,30 @@ namespace OpenSim.Region.Framework.Scenes
457 m_updateList[obj.UUID] = obj; 498 m_updateList[obj.UUID] = obj;
458 } 499 }
459 500
501 public void FireAttachToBackup(SceneObjectGroup obj)
502 {
503 if (OnAttachToBackup != null)
504 {
505 OnAttachToBackup(obj);
506 }
507 }
508
509 public void FireDetachFromBackup(SceneObjectGroup obj)
510 {
511 if (OnDetachFromBackup != null)
512 {
513 OnDetachFromBackup(obj);
514 }
515 }
516
517 public void FireChangeBackup(SceneObjectGroup obj)
518 {
519 if (OnChangeBackup != null)
520 {
521 OnChangeBackup(obj);
522 }
523 }
524
460 /// <summary> 525 /// <summary>
461 /// Process all pending updates 526 /// Process all pending updates
462 /// </summary> 527 /// </summary>
@@ -592,7 +657,8 @@ namespace OpenSim.Region.Framework.Scenes
592 657
593 Entities[presence.UUID] = presence; 658 Entities[presence.UUID] = presence;
594 659
595 lock (m_presenceLock) 660 m_scenePresencesLock.EnterWriteLock();
661 try
596 { 662 {
597 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 663 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
598 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 664 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -616,6 +682,10 @@ namespace OpenSim.Region.Framework.Scenes
616 m_scenePresenceMap = newmap; 682 m_scenePresenceMap = newmap;
617 m_scenePresenceArray = newlist; 683 m_scenePresenceArray = newlist;
618 } 684 }
685 finally
686 {
687 m_scenePresencesLock.ExitWriteLock();
688 }
619 } 689 }
620 690
621 /// <summary> 691 /// <summary>
@@ -630,7 +700,8 @@ namespace OpenSim.Region.Framework.Scenes
630 agentID); 700 agentID);
631 } 701 }
632 702
633 lock (m_presenceLock) 703 m_scenePresencesLock.EnterWriteLock();
704 try
634 { 705 {
635 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 706 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
636 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 707 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -652,6 +723,10 @@ namespace OpenSim.Region.Framework.Scenes
652 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 723 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
653 } 724 }
654 } 725 }
726 finally
727 {
728 m_scenePresencesLock.ExitWriteLock();
729 }
655 } 730 }
656 731
657 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 732 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -775,6 +850,11 @@ namespace OpenSim.Region.Framework.Scenes
775 return m_scenePresenceArray; 850 return m_scenePresenceArray;
776 } 851 }
777 852
853 public int GetNumberOfScenePresences()
854 {
855 return m_scenePresenceArray.Count;
856 }
857
778 /// <summary> 858 /// <summary>
779 /// Request a scene presence by UUID. Fast, indexed lookup. 859 /// Request a scene presence by UUID. Fast, indexed lookup.
780 /// </summary> 860 /// </summary>
@@ -1068,9 +1148,11 @@ namespace OpenSim.Region.Framework.Scenes
1068 /// <param name="action"></param> 1148 /// <param name="action"></param>
1069 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1149 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1070 { 1150 {
1071 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1151 EntityBase[] objlist = Entities.GetAllByType<SceneObjectGroup>();
1072 foreach (SceneObjectGroup obj in objlist) 1152 foreach (EntityBase ent in objlist)
1073 { 1153 {
1154 SceneObjectGroup obj = (SceneObjectGroup)ent;
1155
1074 try 1156 try
1075 { 1157 {
1076 action(obj); 1158 action(obj);
@@ -1281,8 +1363,13 @@ namespace OpenSim.Region.Framework.Scenes
1281 { 1363 {
1282 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1364 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1283 { 1365 {
1284 if (m_parentScene.AttachmentsModule != null) 1366 // Set the new attachment point data in the object
1285 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1367 byte attachmentPoint = group.GetAttachmentPoint();
1368 group.UpdateGroupPosition(pos);
1369 group.RootPart.IsAttachment = false;
1370 group.AbsolutePosition = group.RootPart.AttachedPos;
1371 group.SetAttachmentPoint(attachmentPoint);
1372 group.HasGroupChanged = true;
1286 } 1373 }
1287 else 1374 else
1288 { 1375 {
@@ -1526,10 +1613,13 @@ namespace OpenSim.Region.Framework.Scenes
1526 /// <param name="childPrims"></param> 1613 /// <param name="childPrims"></param>
1527 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1614 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1528 { 1615 {
1616 SceneObjectGroup parentGroup = root.ParentGroup;
1617 if (parentGroup == null) return;
1529 Monitor.Enter(m_updateLock); 1618 Monitor.Enter(m_updateLock);
1619
1530 try 1620 try
1531 { 1621 {
1532 SceneObjectGroup parentGroup = root.ParentGroup; 1622 parentGroup.areUpdatesSuspended = true;
1533 1623
1534 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1624 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1535 if (parentGroup != null) 1625 if (parentGroup != null)
@@ -1541,11 +1631,6 @@ namespace OpenSim.Region.Framework.Scenes
1541 1631
1542 if (child != null) 1632 if (child != null)
1543 { 1633 {
1544 // Make sure no child prim is set for sale
1545 // So that, on delink, no prims are unwittingly
1546 // left for sale and sold off
1547 child.RootPart.ObjectSaleType = 0;
1548 child.RootPart.SalePrice = 10;
1549 childGroups.Add(child); 1634 childGroups.Add(child);
1550 } 1635 }
1551 } 1636 }
@@ -1568,12 +1653,13 @@ namespace OpenSim.Region.Framework.Scenes
1568 // occur on link to invoke this elsewhere (such as object selection) 1653 // occur on link to invoke this elsewhere (such as object selection)
1569 parentGroup.RootPart.CreateSelected = true; 1654 parentGroup.RootPart.CreateSelected = true;
1570 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1655 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1571 parentGroup.HasGroupChanged = true;
1572 parentGroup.ScheduleGroupForFullUpdate();
1573
1574 } 1656 }
1575 finally 1657 finally
1576 { 1658 {
1659 parentGroup.areUpdatesSuspended = false;
1660 parentGroup.HasGroupChanged = true;
1661 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1662 parentGroup.ScheduleGroupForFullUpdate();
1577 Monitor.Exit(m_updateLock); 1663 Monitor.Exit(m_updateLock);
1578 } 1664 }
1579 } 1665 }
@@ -1605,21 +1691,24 @@ namespace OpenSim.Region.Framework.Scenes
1605 1691
1606 SceneObjectGroup group = part.ParentGroup; 1692 SceneObjectGroup group = part.ParentGroup;
1607 if (!affectedGroups.Contains(group)) 1693 if (!affectedGroups.Contains(group))
1694 {
1695 group.areUpdatesSuspended = true;
1608 affectedGroups.Add(group); 1696 affectedGroups.Add(group);
1697 }
1609 } 1698 }
1610 } 1699 }
1611 } 1700 }
1612 1701
1613 foreach (SceneObjectPart child in childParts) 1702 if (childParts.Count > 0)
1614 { 1703 {
1615 // Unlink all child parts from their groups 1704 foreach (SceneObjectPart child in childParts)
1616 // 1705 {
1617 child.ParentGroup.DelinkFromGroup(child, true); 1706 // Unlink all child parts from their groups
1618 1707 //
1619 // These are not in affected groups and will not be 1708 child.ParentGroup.DelinkFromGroup(child, true);
1620 // handled further. Do the honors here. 1709 child.ParentGroup.HasGroupChanged = true;
1621 child.ParentGroup.HasGroupChanged = true; 1710 child.ParentGroup.ScheduleGroupForFullUpdate();
1622 child.ParentGroup.ScheduleGroupForFullUpdate(); 1711 }
1623 } 1712 }
1624 1713
1625 foreach (SceneObjectPart root in rootParts) 1714 foreach (SceneObjectPart root in rootParts)
@@ -1629,56 +1718,68 @@ namespace OpenSim.Region.Framework.Scenes
1629 // However, editing linked parts and unlinking may be different 1718 // However, editing linked parts and unlinking may be different
1630 // 1719 //
1631 SceneObjectGroup group = root.ParentGroup; 1720 SceneObjectGroup group = root.ParentGroup;
1721 group.areUpdatesSuspended = true;
1632 1722
1633 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1723 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1634 int numChildren = newSet.Count; 1724 int numChildren = newSet.Count;
1635 1725
1726 if (numChildren == 1)
1727 break;
1728
1636 // If there are prims left in a link set, but the root is 1729 // If there are prims left in a link set, but the root is
1637 // slated for unlink, we need to do this 1730 // slated for unlink, we need to do this
1731 // Unlink the remaining set
1638 // 1732 //
1639 if (numChildren != 1) 1733 bool sendEventsToRemainder = true;
1640 { 1734 if (numChildren > 1)
1641 // Unlink the remaining set 1735 sendEventsToRemainder = false;
1642 //
1643 bool sendEventsToRemainder = true;
1644 if (numChildren > 1)
1645 sendEventsToRemainder = false;
1646 1736
1647 foreach (SceneObjectPart p in newSet) 1737 foreach (SceneObjectPart p in newSet)
1738 {
1739 if (p != group.RootPart)
1648 { 1740 {
1649 if (p != group.RootPart) 1741 group.DelinkFromGroup(p, sendEventsToRemainder);
1650 group.DelinkFromGroup(p, sendEventsToRemainder); 1742 if (numChildren > 2)
1743 {
1744 p.ParentGroup.areUpdatesSuspended = true;
1745 }
1746 else
1747 {
1748 p.ParentGroup.HasGroupChanged = true;
1749 p.ParentGroup.ScheduleGroupForFullUpdate();
1750 }
1651 } 1751 }
1752 }
1753
1754 // If there is more than one prim remaining, we
1755 // need to re-link
1756 //
1757 if (numChildren > 2)
1758 {
1759 // Remove old root
1760 //
1761 if (newSet.Contains(root))
1762 newSet.Remove(root);
1652 1763
1653 // If there is more than one prim remaining, we 1764 // Preserve link ordering
1654 // need to re-link
1655 // 1765 //
1656 if (numChildren > 2) 1766 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1657 { 1767 {
1658 // Remove old root 1768 return a.LinkNum.CompareTo(b.LinkNum);
1659 // 1769 });
1660 if (newSet.Contains(root))
1661 newSet.Remove(root);
1662
1663 // Preserve link ordering
1664 //
1665 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1666 {
1667 return a.LinkNum.CompareTo(b.LinkNum);
1668 });
1669 1770
1670 // Determine new root 1771 // Determine new root
1671 // 1772 //
1672 SceneObjectPart newRoot = newSet[0]; 1773 SceneObjectPart newRoot = newSet[0];
1673 newSet.RemoveAt(0); 1774 newSet.RemoveAt(0);
1674 1775
1675 foreach (SceneObjectPart newChild in newSet) 1776 foreach (SceneObjectPart newChild in newSet)
1676 newChild.UpdateFlag = 0; 1777 newChild.UpdateFlag = 0;
1677 1778
1678 LinkObjects(newRoot, newSet); 1779 newRoot.ParentGroup.areUpdatesSuspended = true;
1679 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1780 LinkObjects(newRoot, newSet);
1680 affectedGroups.Add(newRoot.ParentGroup); 1781 if (!affectedGroups.Contains(newRoot.ParentGroup))
1681 } 1782 affectedGroups.Add(newRoot.ParentGroup);
1682 } 1783 }
1683 } 1784 }
1684 1785
@@ -1686,8 +1787,14 @@ namespace OpenSim.Region.Framework.Scenes
1686 // 1787 //
1687 foreach (SceneObjectGroup g in affectedGroups) 1788 foreach (SceneObjectGroup g in affectedGroups)
1688 { 1789 {
1790 // Child prims that have been unlinked and deleted will
1791 // return unless the root is deleted. This will remove them
1792 // from the database. They will be rewritten immediately,
1793 // minus the rows for the unlinked child prims.
1794 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1689 g.TriggerScriptChangedEvent(Changed.LINK); 1795 g.TriggerScriptChangedEvent(Changed.LINK);
1690 g.HasGroupChanged = true; // Persist 1796 g.HasGroupChanged = true; // Persist
1797 g.areUpdatesSuspended = false;
1691 g.ScheduleGroupForFullUpdate(); 1798 g.ScheduleGroupForFullUpdate();
1692 } 1799 }
1693 } 1800 }
@@ -1802,9 +1909,6 @@ namespace OpenSim.Region.Framework.Scenes
1802 child.ApplyNextOwnerPermissions(); 1909 child.ApplyNextOwnerPermissions();
1803 } 1910 }
1804 } 1911 }
1805
1806 copy.RootPart.ObjectSaleType = 0;
1807 copy.RootPart.SalePrice = 10;
1808 } 1912 }
1809 1913
1810 Entities.Add(copy); 1914 Entities.Add(copy);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index e8095c0..0b545c4 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();
@@ -376,6 +372,9 @@ namespace OpenSim.Region.Framework.Scenes
376 372
377 public void ResumeScripts() 373 public void ResumeScripts()
378 { 374 {
375 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
376 return;
377
379 SceneObjectPart[] parts = m_parts.GetArray(); 378 SceneObjectPart[] parts = m_parts.GetArray();
380 for (int i = 0; i < parts.Length; i++) 379 for (int i = 0; i < parts.Length; i++)
381 parts[i].Inventory.ResumeScripts(); 380 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index f17fb28..6e0fc43 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -29,6 +29,7 @@ using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -105,8 +106,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 106 /// since the group's last persistent backup
106 /// </summary> 107 /// </summary>
107 private bool m_hasGroupChanged = false; 108 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 109 private long timeFirstChanged = 0;
109 private long timeLastChanged; 110 private long timeLastChanged = 0;
111 private long m_maxPersistTime = 0;
112 private long m_minPersistTime = 0;
113 private Random m_rand;
114 private bool m_suspendUpdates;
115 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
116
117 public bool areUpdatesSuspended
118 {
119 get
120 {
121 return m_suspendUpdates;
122 }
123 set
124 {
125 m_suspendUpdates = value;
126 if (!value)
127 {
128 QueueForUpdateCheck();
129 }
130 }
131 }
110 132
111 public bool HasGroupChanged 133 public bool HasGroupChanged
112 { 134 {
@@ -114,9 +136,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 136 {
115 if (value) 137 if (value)
116 { 138 {
139 if (m_isBackedUp)
140 {
141 m_scene.SceneGraph.FireChangeBackup(this);
142 }
117 timeLastChanged = DateTime.Now.Ticks; 143 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 144 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 145 timeFirstChanged = DateTime.Now.Ticks;
146 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
147 {
148 if (m_rand == null)
149 {
150 byte[] val = new byte[16];
151 m_rootPart.UUID.ToBytes(val, 0);
152 m_rand = new Random(BitConverter.ToInt32(val, 0));
153 }
154
155 if (m_scene.GetRootAgentCount() == 0)
156 {
157 //If the region is empty, this change has been made by an automated process
158 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
159
160 float factor = 1.5f + (float)(m_rand.NextDouble());
161 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
162 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
163 }
164 else
165 {
166 //If the region is not empty, we want to obey the minimum and maximum persist times
167 //but add a random factor so we stagger the object persistance a little
168 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
169 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
170 }
171 }
120 } 172 }
121 m_hasGroupChanged = value; 173 m_hasGroupChanged = value;
122 174
@@ -141,8 +193,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 193 return false;
142 if (m_scene.ShuttingDown) 194 if (m_scene.ShuttingDown)
143 return true; 195 return true;
196
197 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
198 {
199 m_maxPersistTime = m_scene.m_persistAfter;
200 m_minPersistTime = m_scene.m_dontPersistBefore;
201 }
202
144 long currentTime = DateTime.Now.Ticks; 203 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 204
205 if (timeLastChanged == 0) timeLastChanged = currentTime;
206 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
207
208 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 209 return true;
147 return false; 210 return false;
148 } 211 }
@@ -185,10 +248,10 @@ namespace OpenSim.Region.Framework.Scenes
185 248
186 private bool m_scriptListens_atTarget; 249 private bool m_scriptListens_atTarget;
187 private bool m_scriptListens_notAtTarget; 250 private bool m_scriptListens_notAtTarget;
188
189 private bool m_scriptListens_atRotTarget; 251 private bool m_scriptListens_atRotTarget;
190 private bool m_scriptListens_notAtRotTarget; 252 private bool m_scriptListens_notAtRotTarget;
191 253
254 public bool m_dupeInProgress = false;
192 internal Dictionary<UUID, string> m_savedScriptState; 255 internal Dictionary<UUID, string> m_savedScriptState;
193 256
194 #region Properties 257 #region Properties
@@ -228,7 +291,13 @@ namespace OpenSim.Region.Framework.Scenes
228 public virtual Quaternion Rotation 291 public virtual Quaternion Rotation
229 { 292 {
230 get { return m_rotation; } 293 get { return m_rotation; }
231 set { m_rotation = value; } 294 set {
295 foreach(SceneObjectPart p in m_parts.GetArray())
296 {
297 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
298 }
299 m_rotation = value;
300 }
232 } 301 }
233 302
234 public Quaternion GroupRotation 303 public Quaternion GroupRotation
@@ -302,7 +371,11 @@ namespace OpenSim.Region.Framework.Scenes
302 { 371 {
303 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 372 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
304 } 373 }
305 374
375 foreach (SceneObjectPart part in m_parts.GetArray())
376 {
377 part.IgnoreUndoUpdate = true;
378 }
306 if (RootPart.GetStatusSandbox()) 379 if (RootPart.GetStatusSandbox())
307 { 380 {
308 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 381 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -313,10 +386,31 @@ namespace OpenSim.Region.Framework.Scenes
313 return; 386 return;
314 } 387 }
315 } 388 }
316
317 SceneObjectPart[] parts = m_parts.GetArray(); 389 SceneObjectPart[] parts = m_parts.GetArray();
318 for (int i = 0; i < parts.Length; i++) 390 foreach (SceneObjectPart part in parts)
319 parts[i].GroupPosition = val; 391 {
392 part.IgnoreUndoUpdate = false;
393 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
394 part.GroupPosition = val;
395 if (!m_dupeInProgress)
396 {
397 part.TriggerScriptChangedEvent(Changed.POSITION);
398 }
399 }
400 if (!m_dupeInProgress)
401 {
402 foreach (ScenePresence av in m_linkedAvatars)
403 {
404 SceneObjectPart p;
405 if (m_parts.TryGetValue(av.LinkedPrim, out p))
406 {
407 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
408 av.AbsolutePosition += offset;
409 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
410 av.SendAvatarDataToAllAgents();
411 }
412 }
413 }
320 414
321 //if (m_rootPart.PhysActor != null) 415 //if (m_rootPart.PhysActor != null)
322 //{ 416 //{
@@ -467,6 +561,7 @@ namespace OpenSim.Region.Framework.Scenes
467 /// </summary> 561 /// </summary>
468 public SceneObjectGroup() 562 public SceneObjectGroup()
469 { 563 {
564
470 } 565 }
471 566
472 /// <summary> 567 /// <summary>
@@ -483,7 +578,7 @@ namespace OpenSim.Region.Framework.Scenes
483 /// Constructor. This object is added to the scene later via AttachToScene() 578 /// Constructor. This object is added to the scene later via AttachToScene()
484 /// </summary> 579 /// </summary>
485 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 580 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
486 { 581 {
487 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 582 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
488 } 583 }
489 584
@@ -531,6 +626,9 @@ namespace OpenSim.Region.Framework.Scenes
531 /// </summary> 626 /// </summary>
532 public virtual void AttachToBackup() 627 public virtual void AttachToBackup()
533 { 628 {
629 if (IsAttachment) return;
630 m_scene.SceneGraph.FireAttachToBackup(this);
631
534 if (InSceneBackup) 632 if (InSceneBackup)
535 { 633 {
536 //m_log.DebugFormat( 634 //m_log.DebugFormat(
@@ -646,9 +744,9 @@ namespace OpenSim.Region.Framework.Scenes
646 result.normal = inter.normal; 744 result.normal = inter.normal;
647 result.distance = inter.distance; 745 result.distance = inter.distance;
648 } 746 }
747
649 } 748 }
650 } 749 }
651
652 return result; 750 return result;
653 } 751 }
654 752
@@ -668,17 +766,19 @@ namespace OpenSim.Region.Framework.Scenes
668 minZ = 8192f; 766 minZ = 8192f;
669 767
670 SceneObjectPart[] parts = m_parts.GetArray(); 768 SceneObjectPart[] parts = m_parts.GetArray();
671 for (int i = 0; i < parts.Length; i++) 769 foreach (SceneObjectPart part in parts)
672 { 770 {
673 SceneObjectPart part = parts[i];
674
675 Vector3 worldPos = part.GetWorldPosition(); 771 Vector3 worldPos = part.GetWorldPosition();
676 Vector3 offset = worldPos - AbsolutePosition; 772 Vector3 offset = worldPos - AbsolutePosition;
677 Quaternion worldRot; 773 Quaternion worldRot;
678 if (part.ParentID == 0) 774 if (part.ParentID == 0)
775 {
679 worldRot = part.RotationOffset; 776 worldRot = part.RotationOffset;
777 }
680 else 778 else
779 {
681 worldRot = part.GetWorldRotation(); 780 worldRot = part.GetWorldRotation();
781 }
682 782
683 Vector3 frontTopLeft; 783 Vector3 frontTopLeft;
684 Vector3 frontTopRight; 784 Vector3 frontTopRight;
@@ -690,6 +790,8 @@ namespace OpenSim.Region.Framework.Scenes
690 Vector3 backBottomLeft; 790 Vector3 backBottomLeft;
691 Vector3 backBottomRight; 791 Vector3 backBottomRight;
692 792
793 // Vector3[] corners = new Vector3[8];
794
693 Vector3 orig = Vector3.Zero; 795 Vector3 orig = Vector3.Zero;
694 796
695 frontTopLeft.X = orig.X - (part.Scale.X / 2); 797 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -724,6 +826,38 @@ namespace OpenSim.Region.Framework.Scenes
724 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 826 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
725 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 827 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
726 828
829
830
831 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
832 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
833 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
834 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
835 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
836 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
837 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
838 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
839
840 //for (int i = 0; i < 8; i++)
841 //{
842 // corners[i] = corners[i] * worldRot;
843 // corners[i] += offset;
844
845 // if (corners[i].X > maxX)
846 // maxX = corners[i].X;
847 // if (corners[i].X < minX)
848 // minX = corners[i].X;
849
850 // if (corners[i].Y > maxY)
851 // maxY = corners[i].Y;
852 // if (corners[i].Y < minY)
853 // minY = corners[i].Y;
854
855 // if (corners[i].Z > maxZ)
856 // maxZ = corners[i].Y;
857 // if (corners[i].Z < minZ)
858 // minZ = corners[i].Z;
859 //}
860
727 frontTopLeft = frontTopLeft * worldRot; 861 frontTopLeft = frontTopLeft * worldRot;
728 frontTopRight = frontTopRight * worldRot; 862 frontTopRight = frontTopRight * worldRot;
729 frontBottomLeft = frontBottomLeft * worldRot; 863 frontBottomLeft = frontBottomLeft * worldRot;
@@ -745,6 +879,15 @@ namespace OpenSim.Region.Framework.Scenes
745 backTopLeft += offset; 879 backTopLeft += offset;
746 backTopRight += offset; 880 backTopRight += offset;
747 881
882 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
883 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
884 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
885 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
886 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
887 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
888 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
889 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
890
748 if (frontTopRight.X > maxX) 891 if (frontTopRight.X > maxX)
749 maxX = frontTopRight.X; 892 maxX = frontTopRight.X;
750 if (frontTopLeft.X > maxX) 893 if (frontTopLeft.X > maxX)
@@ -890,15 +1033,20 @@ namespace OpenSim.Region.Framework.Scenes
890 1033
891 public void SaveScriptedState(XmlTextWriter writer) 1034 public void SaveScriptedState(XmlTextWriter writer)
892 { 1035 {
1036 SaveScriptedState(writer, false);
1037 }
1038
1039 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1040 {
893 XmlDocument doc = new XmlDocument(); 1041 XmlDocument doc = new XmlDocument();
894 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1042 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
895 1043
896 SceneObjectPart[] parts = m_parts.GetArray(); 1044 SceneObjectPart[] parts = m_parts.GetArray();
897 for (int i = 0; i < parts.Length; i++) 1045 for (int i = 0; i < parts.Length; i++)
898 { 1046 {
899 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1047 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
900 foreach (KeyValuePair<UUID, string> kvp in pstates) 1048 foreach (KeyValuePair<UUID, string> kvp in pstates)
901 states.Add(kvp.Key, kvp.Value); 1049 states[kvp.Key] = kvp.Value;
902 } 1050 }
903 1051
904 if (states.Count > 0) 1052 if (states.Count > 0)
@@ -917,6 +1065,118 @@ namespace OpenSim.Region.Framework.Scenes
917 } 1065 }
918 } 1066 }
919 1067
1068 /// <summary>
1069 /// Add the avatar to this linkset (avatar is sat).
1070 /// </summary>
1071 /// <param name="agentID"></param>
1072 public void AddAvatar(UUID agentID)
1073 {
1074 ScenePresence presence;
1075 if (m_scene.TryGetScenePresence(agentID, out presence))
1076 {
1077 if (!m_linkedAvatars.Contains(presence))
1078 {
1079 m_linkedAvatars.Add(presence);
1080 }
1081 }
1082 }
1083
1084 /// <summary>
1085 /// Delete the avatar from this linkset (avatar is unsat).
1086 /// </summary>
1087 /// <param name="agentID"></param>
1088 public void DeleteAvatar(UUID agentID)
1089 {
1090 ScenePresence presence;
1091 if (m_scene.TryGetScenePresence(agentID, out presence))
1092 {
1093 if (m_linkedAvatars.Contains(presence))
1094 {
1095 m_linkedAvatars.Remove(presence);
1096 }
1097 }
1098 }
1099
1100 /// <summary>
1101 /// Returns the list of linked presences (avatars sat on this group)
1102 /// </summary>
1103 /// <param name="agentID"></param>
1104 public List<ScenePresence> GetLinkedAvatars()
1105 {
1106 return m_linkedAvatars;
1107 }
1108
1109 /// <summary>
1110 /// Attach this scene object to the given avatar.
1111 /// </summary>
1112 /// <param name="agentID"></param>
1113 /// <param name="attachmentpoint"></param>
1114 /// <param name="AttachOffset"></param>
1115 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent)
1116 {
1117 ScenePresence avatar = m_scene.GetScenePresence(agentID);
1118 if (avatar != null)
1119 {
1120 // don't attach attachments to child agents
1121 if (avatar.IsChildAgent) return;
1122
1123// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
1124
1125 DetachFromBackup();
1126
1127 // Remove from database and parcel prim count
1128 m_scene.DeleteFromStorage(UUID);
1129 m_scene.EventManager.TriggerParcelPrimCountTainted();
1130
1131 m_rootPart.AttachedAvatar = agentID;
1132
1133 //Anakin Lohner bug #3839
1134 lock (m_parts)
1135 {
1136 foreach (SceneObjectPart p in m_parts.GetArray())
1137 {
1138 p.AttachedAvatar = agentID;
1139 }
1140 }
1141
1142 if (m_rootPart.PhysActor != null)
1143 {
1144 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor);
1145 m_rootPart.PhysActor = null;
1146 }
1147
1148 AbsolutePosition = AttachOffset;
1149 m_rootPart.AttachedPos = AttachOffset;
1150 m_rootPart.IsAttachment = true;
1151
1152 m_rootPart.SetParentLocalId(avatar.LocalId);
1153 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
1154
1155 avatar.AddAttachment(this);
1156
1157 if (!silent)
1158 {
1159 // Killing it here will cause the client to deselect it
1160 // It then reappears on the avatar, deselected
1161 // through the full update below
1162 //
1163 if (IsSelected)
1164 {
1165 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1166 }
1167
1168 IsSelected = false; // fudge....
1169 ScheduleGroupForFullUpdate();
1170 }
1171 }
1172 else
1173 {
1174 m_log.WarnFormat(
1175 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1176 UUID, agentID, Scene.RegionInfo.RegionName);
1177 }
1178 }
1179
920 public byte GetAttachmentPoint() 1180 public byte GetAttachmentPoint()
921 { 1181 {
922 return m_rootPart.Shape.State; 1182 return m_rootPart.Shape.State;
@@ -1043,7 +1303,10 @@ namespace OpenSim.Region.Framework.Scenes
1043 public void AddPart(SceneObjectPart part) 1303 public void AddPart(SceneObjectPart part)
1044 { 1304 {
1045 part.SetParent(this); 1305 part.SetParent(this);
1046 part.LinkNum = m_parts.Add(part.UUID, part); 1306 m_parts.Add(part.UUID, part);
1307
1308 part.LinkNum = m_parts.Count;
1309
1047 if (part.LinkNum == 2 && RootPart != null) 1310 if (part.LinkNum == 2 && RootPart != null)
1048 RootPart.LinkNum = 1; 1311 RootPart.LinkNum = 1;
1049 } 1312 }
@@ -1127,7 +1390,7 @@ namespace OpenSim.Region.Framework.Scenes
1127 1390
1128 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1391 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1129 { 1392 {
1130 part.StoreUndoState(); 1393 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1131 part.OnGrab(offsetPos, remoteClient); 1394 part.OnGrab(offsetPos, remoteClient);
1132 } 1395 }
1133 1396
@@ -1147,6 +1410,11 @@ namespace OpenSim.Region.Framework.Scenes
1147 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1410 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1148 public void DeleteGroupFromScene(bool silent) 1411 public void DeleteGroupFromScene(bool silent)
1149 { 1412 {
1413 // We need to keep track of this state in case this group is still queued for backup.
1414 m_isDeleted = true;
1415
1416 DetachFromBackup();
1417
1150 SceneObjectPart[] parts = m_parts.GetArray(); 1418 SceneObjectPart[] parts = m_parts.GetArray();
1151 for (int i = 0; i < parts.Length; i++) 1419 for (int i = 0; i < parts.Length; i++)
1152 { 1420 {
@@ -1158,13 +1426,11 @@ namespace OpenSim.Region.Framework.Scenes
1158 avatar.StandUp(); 1426 avatar.StandUp();
1159 1427
1160 if (!silent) 1428 if (!silent)
1161 {
1162 part.UpdateFlag = 0; 1429 part.UpdateFlag = 0;
1163 if (part == m_rootPart)
1164 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1165 }
1166 }); 1430 });
1167 } 1431 }
1432
1433
1168 } 1434 }
1169 1435
1170 public void AddScriptLPS(int count) 1436 public void AddScriptLPS(int count)
@@ -1261,7 +1527,12 @@ namespace OpenSim.Region.Framework.Scenes
1261 1527
1262 public void SetOwnerId(UUID userId) 1528 public void SetOwnerId(UUID userId)
1263 { 1529 {
1264 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1530 ForEachPart(delegate(SceneObjectPart part)
1531 {
1532
1533 part.OwnerID = userId;
1534
1535 });
1265 } 1536 }
1266 1537
1267 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1538 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1293,11 +1564,17 @@ namespace OpenSim.Region.Framework.Scenes
1293 return; 1564 return;
1294 } 1565 }
1295 1566
1567 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1568 return;
1569
1296 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1570 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1297 // any exception propogate upwards. 1571 // any exception propogate upwards.
1298 try 1572 try
1299 { 1573 {
1300 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1574 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1575 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1576 m_scene.LoadingPrims) // Land may not be valid yet
1577
1301 { 1578 {
1302 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1579 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1303 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1580 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1322,6 +1599,7 @@ namespace OpenSim.Region.Framework.Scenes
1322 } 1599 }
1323 } 1600 }
1324 } 1601 }
1602
1325 } 1603 }
1326 1604
1327 if (HasGroupChanged) 1605 if (HasGroupChanged)
@@ -1329,6 +1607,20 @@ namespace OpenSim.Region.Framework.Scenes
1329 // don't backup while it's selected or you're asking for changes mid stream. 1607 // don't backup while it's selected or you're asking for changes mid stream.
1330 if (isTimeToPersist() || forcedBackup) 1608 if (isTimeToPersist() || forcedBackup)
1331 { 1609 {
1610 if (m_rootPart.PhysActor != null &&
1611 (!m_rootPart.PhysActor.IsPhysical))
1612 {
1613 // Possible ghost prim
1614 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1615 {
1616 foreach (SceneObjectPart part in m_parts.GetArray())
1617 {
1618 // Re-set physics actor positions and
1619 // orientations
1620 part.GroupPosition = m_rootPart.GroupPosition;
1621 }
1622 }
1623 }
1332// m_log.DebugFormat( 1624// m_log.DebugFormat(
1333// "[SCENE]: Storing {0}, {1} in {2}", 1625// "[SCENE]: Storing {0}, {1} in {2}",
1334// Name, UUID, m_scene.RegionInfo.RegionName); 1626// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1392,81 +1684,90 @@ namespace OpenSim.Region.Framework.Scenes
1392 /// <returns></returns> 1684 /// <returns></returns>
1393 public SceneObjectGroup Copy(bool userExposed) 1685 public SceneObjectGroup Copy(bool userExposed)
1394 { 1686 {
1395 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1687 SceneObjectGroup dupe;
1396 dupe.m_isBackedUp = false; 1688 try
1397 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1689 {
1690 m_dupeInProgress = true;
1691 dupe = (SceneObjectGroup)MemberwiseClone();
1692 dupe.m_isBackedUp = false;
1693 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1398 1694
1399 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1695 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1400 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1696 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1401 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1697 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1402 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state 1698 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1403 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, 1699 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1404 // then restore it's attachment state 1700 // then restore it's attachment state
1405 1701
1406 // This is only necessary when userExposed is false! 1702 // This is only necessary when userExposed is false!
1407 1703
1408 bool previousAttachmentStatus = dupe.RootPart.IsAttachment; 1704 bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
1409
1410 if (!userExposed)
1411 dupe.RootPart.IsAttachment = true;
1412 1705
1413 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1706 if (!userExposed)
1707 dupe.RootPart.IsAttachment = true;
1414 1708
1415 if (!userExposed) 1709 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1416 {
1417 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1418 }
1419 1710
1420 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1711 if (!userExposed)
1421 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1422
1423 if (userExposed)
1424 dupe.m_rootPart.TrimPermissions();
1425
1426 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1427
1428 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1429 { 1712 {
1430 return p1.LinkNum.CompareTo(p2.LinkNum); 1713 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1431 } 1714 }
1432 );
1433 1715
1434 foreach (SceneObjectPart part in partList) 1716 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1435 { 1717 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1436 if (part.UUID != m_rootPart.UUID) 1718
1719 if (userExposed)
1720 dupe.m_rootPart.TrimPermissions();
1721
1722 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1723
1724 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1725 {
1726 return p1.LinkNum.CompareTo(p2.LinkNum);
1727 }
1728 );
1729
1730 foreach (SceneObjectPart part in partList)
1437 { 1731 {
1438 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1732 if (part.UUID != m_rootPart.UUID)
1439 newPart.LinkNum = part.LinkNum; 1733 {
1440 } 1734 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1441 1735
1442 // Need to duplicate the physics actor as well 1736 newPart.LinkNum = part.LinkNum;
1443 if (part.PhysActor != null && userExposed) 1737 }
1738
1739 // Need to duplicate the physics actor as well
1740 if (part.PhysActor != null && userExposed)
1741 {
1742 PrimitiveBaseShape pbs = part.Shape;
1743
1744 part.PhysActor
1745 = m_scene.PhysicsScene.AddPrimShape(
1746 string.Format("{0}/{1}", part.Name, part.UUID),
1747 pbs,
1748 part.AbsolutePosition,
1749 part.Scale,
1750 part.RotationOffset,
1751 part.PhysActor.IsPhysical);
1752 part.PhysActor.SetMaterial((int)part.Material);
1753
1754 part.PhysActor.LocalID = part.LocalId;
1755 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1756 }
1757 }
1758 if (userExposed)
1444 { 1759 {
1445 PrimitiveBaseShape pbs = part.Shape; 1760 dupe.UpdateParentIDs();
1446 1761 dupe.HasGroupChanged = true;
1447 part.PhysActor 1762 dupe.AttachToBackup();
1448 = m_scene.PhysicsScene.AddPrimShape( 1763
1449 string.Format("{0}/{1}", part.Name, part.UUID), 1764 ScheduleGroupForFullUpdate();
1450 pbs,
1451 part.AbsolutePosition,
1452 part.Scale,
1453 part.RotationOffset,
1454 part.PhysActor.IsPhysical);
1455
1456 part.PhysActor.LocalID = part.LocalId;
1457 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1458 } 1765 }
1459 } 1766 }
1460 1767 finally
1461 if (userExposed)
1462 { 1768 {
1463 dupe.UpdateParentIDs(); 1769 m_dupeInProgress = false;
1464 dupe.HasGroupChanged = true;
1465 dupe.AttachToBackup();
1466
1467 ScheduleGroupForFullUpdate();
1468 } 1770 }
1469
1470 return dupe; 1771 return dupe;
1471 } 1772 }
1472 1773
@@ -1657,13 +1958,40 @@ namespace OpenSim.Region.Framework.Scenes
1657 } 1958 }
1658 } 1959 }
1659 1960
1961 public void rotLookAt(Quaternion target, float strength, float damping)
1962 {
1963 SceneObjectPart rootpart = m_rootPart;
1964 if (rootpart != null)
1965 {
1966 if (IsAttachment)
1967 {
1968 /*
1969 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1970 if (avatar != null)
1971 {
1972 Rotate the Av?
1973 } */
1974 }
1975 else
1976 {
1977 if (rootpart.PhysActor != null)
1978 { // APID must be implemented in your physics system for this to function.
1979 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
1980 rootpart.PhysActor.APIDStrength = strength;
1981 rootpart.PhysActor.APIDDamping = damping;
1982 rootpart.PhysActor.APIDActive = true;
1983 }
1984 }
1985 }
1986 }
1987
1660 public void stopLookAt() 1988 public void stopLookAt()
1661 { 1989 {
1662 SceneObjectPart rootpart = m_rootPart; 1990 SceneObjectPart rootpart = m_rootPart;
1663 if (rootpart != null) 1991 if (rootpart != null)
1664 { 1992 {
1665 if (rootpart.PhysActor != null) 1993 if (rootpart.PhysActor != null)
1666 { 1994 { // APID must be implemented in your physics system for this to function.
1667 rootpart.PhysActor.APIDActive = false; 1995 rootpart.PhysActor.APIDActive = false;
1668 } 1996 }
1669 } 1997 }
@@ -1729,6 +2057,8 @@ namespace OpenSim.Region.Framework.Scenes
1729 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2057 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1730 { 2058 {
1731 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2059 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2060 newPart.SetParent(this);
2061
1732 AddPart(newPart); 2062 AddPart(newPart);
1733 2063
1734 SetPartAsNonRoot(newPart); 2064 SetPartAsNonRoot(newPart);
@@ -1875,11 +2205,11 @@ namespace OpenSim.Region.Framework.Scenes
1875 /// Immediately send a full update for this scene object. 2205 /// Immediately send a full update for this scene object.
1876 /// </summary> 2206 /// </summary>
1877 public void SendGroupFullUpdate() 2207 public void SendGroupFullUpdate()
1878 { 2208 {
1879 if (IsDeleted) 2209 if (IsDeleted)
1880 return; 2210 return;
1881 2211
1882// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2212// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1883 2213
1884 RootPart.SendFullUpdateToAllClients(); 2214 RootPart.SendFullUpdateToAllClients();
1885 2215
@@ -2068,12 +2398,15 @@ namespace OpenSim.Region.Framework.Scenes
2068 part.LinkNum += objectGroup.PrimCount; 2398 part.LinkNum += objectGroup.PrimCount;
2069 } 2399 }
2070 } 2400 }
2401 }
2071 2402
2072 linkPart.LinkNum = 2; 2403 linkPart.LinkNum = 2;
2073 2404
2074 linkPart.SetParent(this); 2405 linkPart.SetParent(this);
2075 linkPart.CreateSelected = true; 2406 linkPart.CreateSelected = true;
2076 2407
2408 lock (m_parts.SyncRoot)
2409 {
2077 //if (linkPart.PhysActor != null) 2410 //if (linkPart.PhysActor != null)
2078 //{ 2411 //{
2079 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2412 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2231,6 +2564,8 @@ namespace OpenSim.Region.Framework.Scenes
2231 /// <param name="objectGroup"></param> 2564 /// <param name="objectGroup"></param>
2232 public virtual void DetachFromBackup() 2565 public virtual void DetachFromBackup()
2233 { 2566 {
2567 m_scene.SceneGraph.FireDetachFromBackup(this);
2568
2234 if (m_isBackedUp) 2569 if (m_isBackedUp)
2235 m_scene.EventManager.OnBackup -= ProcessBackup; 2570 m_scene.EventManager.OnBackup -= ProcessBackup;
2236 2571
@@ -2249,7 +2584,8 @@ namespace OpenSim.Region.Framework.Scenes
2249 2584
2250 axPos *= parentRot; 2585 axPos *= parentRot;
2251 part.OffsetPosition = axPos; 2586 part.OffsetPosition = axPos;
2252 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2587 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2588 part.GroupPosition = newPos;
2253 part.OffsetPosition = Vector3.Zero; 2589 part.OffsetPosition = Vector3.Zero;
2254 part.RotationOffset = worldRot; 2590 part.RotationOffset = worldRot;
2255 2591
@@ -2260,7 +2596,7 @@ namespace OpenSim.Region.Framework.Scenes
2260 2596
2261 part.LinkNum = linkNum; 2597 part.LinkNum = linkNum;
2262 2598
2263 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2599 part.OffsetPosition = newPos - AbsolutePosition;
2264 2600
2265 Quaternion rootRotation = m_rootPart.RotationOffset; 2601 Quaternion rootRotation = m_rootPart.RotationOffset;
2266 2602
@@ -2270,7 +2606,7 @@ namespace OpenSim.Region.Framework.Scenes
2270 2606
2271 parentRot = m_rootPart.RotationOffset; 2607 parentRot = m_rootPart.RotationOffset;
2272 oldRot = part.RotationOffset; 2608 oldRot = part.RotationOffset;
2273 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2609 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2274 part.RotationOffset = newRot; 2610 part.RotationOffset = newRot;
2275 } 2611 }
2276 2612
@@ -2521,8 +2857,12 @@ namespace OpenSim.Region.Framework.Scenes
2521 } 2857 }
2522 } 2858 }
2523 2859
2860 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2524 for (int i = 0; i < parts.Length; i++) 2861 for (int i = 0; i < parts.Length; i++)
2525 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2862 {
2863 if (parts[i] != RootPart)
2864 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2865 }
2526 } 2866 }
2527 } 2867 }
2528 2868
@@ -2535,6 +2875,17 @@ namespace OpenSim.Region.Framework.Scenes
2535 } 2875 }
2536 } 2876 }
2537 2877
2878
2879
2880 /// <summary>
2881 /// Gets the number of parts
2882 /// </summary>
2883 /// <returns></returns>
2884 public int GetPartCount()
2885 {
2886 return Parts.Count();
2887 }
2888
2538 /// <summary> 2889 /// <summary>
2539 /// Update the texture entry for this part 2890 /// Update the texture entry for this part
2540 /// </summary> 2891 /// </summary>
@@ -2596,11 +2947,9 @@ namespace OpenSim.Region.Framework.Scenes
2596 scale.Y = m_scene.m_maxNonphys; 2947 scale.Y = m_scene.m_maxNonphys;
2597 if (scale.Z > m_scene.m_maxNonphys) 2948 if (scale.Z > m_scene.m_maxNonphys)
2598 scale.Z = m_scene.m_maxNonphys; 2949 scale.Z = m_scene.m_maxNonphys;
2599
2600 SceneObjectPart part = GetChildPart(localID); 2950 SceneObjectPart part = GetChildPart(localID);
2601 if (part != null) 2951 if (part != null)
2602 { 2952 {
2603 part.Resize(scale);
2604 if (part.PhysActor != null) 2953 if (part.PhysActor != null)
2605 { 2954 {
2606 if (part.PhysActor.IsPhysical) 2955 if (part.PhysActor.IsPhysical)
@@ -2615,7 +2964,7 @@ namespace OpenSim.Region.Framework.Scenes
2615 part.PhysActor.Size = scale; 2964 part.PhysActor.Size = scale;
2616 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2965 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2617 } 2966 }
2618 //if (part.UUID != m_rootPart.UUID) 2967 part.Resize(scale);
2619 2968
2620 HasGroupChanged = true; 2969 HasGroupChanged = true;
2621 part.TriggerScriptChangedEvent(Changed.SCALE); 2970 part.TriggerScriptChangedEvent(Changed.SCALE);
@@ -2638,7 +2987,6 @@ namespace OpenSim.Region.Framework.Scenes
2638 SceneObjectPart part = GetChildPart(localID); 2987 SceneObjectPart part = GetChildPart(localID);
2639 if (part != null) 2988 if (part != null)
2640 { 2989 {
2641 part.IgnoreUndoUpdate = true;
2642 if (scale.X > m_scene.m_maxNonphys) 2990 if (scale.X > m_scene.m_maxNonphys)
2643 scale.X = m_scene.m_maxNonphys; 2991 scale.X = m_scene.m_maxNonphys;
2644 if (scale.Y > m_scene.m_maxNonphys) 2992 if (scale.Y > m_scene.m_maxNonphys)
@@ -2675,7 +3023,7 @@ namespace OpenSim.Region.Framework.Scenes
2675 3023
2676 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3024 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2677 { 3025 {
2678 if (oldSize.X * x > m_scene.m_maxPhys) 3026 if (oldSize.X*x > m_scene.m_maxPhys)
2679 { 3027 {
2680 f = m_scene.m_maxPhys / oldSize.X; 3028 f = m_scene.m_maxPhys / oldSize.X;
2681 a = f / x; 3029 a = f / x;
@@ -2683,7 +3031,7 @@ namespace OpenSim.Region.Framework.Scenes
2683 y *= a; 3031 y *= a;
2684 z *= a; 3032 z *= a;
2685 } 3033 }
2686 if (oldSize.Y * y > m_scene.m_maxPhys) 3034 if (oldSize.Y*y > m_scene.m_maxPhys)
2687 { 3035 {
2688 f = m_scene.m_maxPhys / oldSize.Y; 3036 f = m_scene.m_maxPhys / oldSize.Y;
2689 a = f / y; 3037 a = f / y;
@@ -2691,7 +3039,7 @@ namespace OpenSim.Region.Framework.Scenes
2691 y *= a; 3039 y *= a;
2692 z *= a; 3040 z *= a;
2693 } 3041 }
2694 if (oldSize.Z * z > m_scene.m_maxPhys) 3042 if (oldSize.Z*z > m_scene.m_maxPhys)
2695 { 3043 {
2696 f = m_scene.m_maxPhys / oldSize.Z; 3044 f = m_scene.m_maxPhys / oldSize.Z;
2697 a = f / z; 3045 a = f / z;
@@ -2702,7 +3050,7 @@ namespace OpenSim.Region.Framework.Scenes
2702 } 3050 }
2703 else 3051 else
2704 { 3052 {
2705 if (oldSize.X * x > m_scene.m_maxNonphys) 3053 if (oldSize.X*x > m_scene.m_maxNonphys)
2706 { 3054 {
2707 f = m_scene.m_maxNonphys / oldSize.X; 3055 f = m_scene.m_maxNonphys / oldSize.X;
2708 a = f / x; 3056 a = f / x;
@@ -2710,7 +3058,7 @@ namespace OpenSim.Region.Framework.Scenes
2710 y *= a; 3058 y *= a;
2711 z *= a; 3059 z *= a;
2712 } 3060 }
2713 if (oldSize.Y * y > m_scene.m_maxNonphys) 3061 if (oldSize.Y*y > m_scene.m_maxNonphys)
2714 { 3062 {
2715 f = m_scene.m_maxNonphys / oldSize.Y; 3063 f = m_scene.m_maxNonphys / oldSize.Y;
2716 a = f / y; 3064 a = f / y;
@@ -2718,7 +3066,7 @@ namespace OpenSim.Region.Framework.Scenes
2718 y *= a; 3066 y *= a;
2719 z *= a; 3067 z *= a;
2720 } 3068 }
2721 if (oldSize.Z * z > m_scene.m_maxNonphys) 3069 if (oldSize.Z*z > m_scene.m_maxNonphys)
2722 { 3070 {
2723 f = m_scene.m_maxNonphys / oldSize.Z; 3071 f = m_scene.m_maxNonphys / oldSize.Z;
2724 a = f / z; 3072 a = f / z;
@@ -2728,7 +3076,6 @@ namespace OpenSim.Region.Framework.Scenes
2728 } 3076 }
2729 } 3077 }
2730 obPart.IgnoreUndoUpdate = false; 3078 obPart.IgnoreUndoUpdate = false;
2731 obPart.StoreUndoState();
2732 } 3079 }
2733 } 3080 }
2734 } 3081 }
@@ -2736,8 +3083,13 @@ namespace OpenSim.Region.Framework.Scenes
2736 Vector3 prevScale = part.Scale; 3083 Vector3 prevScale = part.Scale;
2737 prevScale.X *= x; 3084 prevScale.X *= x;
2738 prevScale.Y *= y; 3085 prevScale.Y *= y;
2739 prevScale.Z *= z; 3086 prevScale.Z *= z;;
3087
3088 part.IgnoreUndoUpdate = false;
3089 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3090 part.IgnoreUndoUpdate = true;
2740 part.Resize(prevScale); 3091 part.Resize(prevScale);
3092 part.IgnoreUndoUpdate = false;
2741 3093
2742 parts = m_parts.GetArray(); 3094 parts = m_parts.GetArray();
2743 for (int i = 0; i < parts.Length; i++) 3095 for (int i = 0; i < parts.Length; i++)
@@ -2746,19 +3098,26 @@ namespace OpenSim.Region.Framework.Scenes
2746 obPart.IgnoreUndoUpdate = true; 3098 obPart.IgnoreUndoUpdate = true;
2747 if (obPart.UUID != m_rootPart.UUID) 3099 if (obPart.UUID != m_rootPart.UUID)
2748 { 3100 {
2749 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3101 if (obPart.UUID != m_rootPart.UUID)
2750 currentpos.X *= x; 3102 {
2751 currentpos.Y *= y; 3103 obPart.IgnoreUndoUpdate = false;
2752 currentpos.Z *= z; 3104 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
2753 Vector3 newSize = new Vector3(obPart.Scale); 3105 obPart.IgnoreUndoUpdate = true;
2754 newSize.X *= x; 3106
2755 newSize.Y *= y; 3107 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2756 newSize.Z *= z; 3108 currentpos.X *= x;
2757 obPart.Resize(newSize); 3109 currentpos.Y *= y;
2758 obPart.UpdateOffSet(currentpos); 3110 currentpos.Z *= z;
3111 Vector3 newSize = new Vector3(obPart.Scale);
3112 newSize.X *= x;
3113 newSize.Y *= y;
3114 newSize.Z *= z;
3115 obPart.Resize(newSize);
3116 obPart.UpdateOffSet(currentpos);
3117 }
3118 obPart.IgnoreUndoUpdate = false;
2759 } 3119 }
2760 obPart.IgnoreUndoUpdate = false; 3120 obPart.IgnoreUndoUpdate = false;
2761 obPart.StoreUndoState();
2762 } 3121 }
2763 3122
2764 if (part.PhysActor != null) 3123 if (part.PhysActor != null)
@@ -2768,7 +3127,6 @@ namespace OpenSim.Region.Framework.Scenes
2768 } 3127 }
2769 3128
2770 part.IgnoreUndoUpdate = false; 3129 part.IgnoreUndoUpdate = false;
2771 part.StoreUndoState();
2772 HasGroupChanged = true; 3130 HasGroupChanged = true;
2773 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); 3131 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
2774 ScheduleGroupForTerseUpdate(); 3132 ScheduleGroupForTerseUpdate();
@@ -2785,14 +3143,11 @@ namespace OpenSim.Region.Framework.Scenes
2785 /// <param name="pos"></param> 3143 /// <param name="pos"></param>
2786 public void UpdateGroupPosition(Vector3 pos) 3144 public void UpdateGroupPosition(Vector3 pos)
2787 { 3145 {
2788 SceneObjectPart[] parts = m_parts.GetArray();
2789 for (int i = 0; i < parts.Length; i++)
2790 parts[i].StoreUndoState();
2791
2792 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3146 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2793 { 3147 {
2794 if (IsAttachment) 3148 if (IsAttachment)
2795 { 3149 {
3150 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2796 m_rootPart.AttachedPos = pos; 3151 m_rootPart.AttachedPos = pos;
2797 } 3152 }
2798 if (RootPart.GetStatusSandbox()) 3153 if (RootPart.GetStatusSandbox())
@@ -2826,7 +3181,7 @@ namespace OpenSim.Region.Framework.Scenes
2826 3181
2827 SceneObjectPart[] parts = m_parts.GetArray(); 3182 SceneObjectPart[] parts = m_parts.GetArray();
2828 for (int i = 0; i < parts.Length; i++) 3183 for (int i = 0; i < parts.Length; i++)
2829 parts[i].StoreUndoState(); 3184 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2830 3185
2831 if (part != null) 3186 if (part != null)
2832 { 3187 {
@@ -2851,7 +3206,7 @@ namespace OpenSim.Region.Framework.Scenes
2851 { 3206 {
2852 SceneObjectPart[] parts = m_parts.GetArray(); 3207 SceneObjectPart[] parts = m_parts.GetArray();
2853 for (int i = 0; i < parts.Length; i++) 3208 for (int i = 0; i < parts.Length; i++)
2854 parts[i].StoreUndoState(); 3209 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2855 3210
2856 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3211 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2857 Vector3 oldPos = 3212 Vector3 oldPos =
@@ -2872,10 +3227,27 @@ namespace OpenSim.Region.Framework.Scenes
2872 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3227 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2873 } 3228 }
2874 3229
2875 AbsolutePosition = newPos; 3230 //We have to set undoing here because otherwise an undo state will be saved
3231 if (!m_rootPart.Undoing)
3232 {
3233 m_rootPart.Undoing = true;
3234 AbsolutePosition = newPos;
3235 m_rootPart.Undoing = false;
3236 }
3237 else
3238 {
3239 AbsolutePosition = newPos;
3240 }
2876 3241
2877 HasGroupChanged = true; 3242 HasGroupChanged = true;
2878 ScheduleGroupForTerseUpdate(); 3243 if (m_rootPart.Undoing)
3244 {
3245 ScheduleGroupForFullUpdate();
3246 }
3247 else
3248 {
3249 ScheduleGroupForTerseUpdate();
3250 }
2879 } 3251 }
2880 3252
2881 public void OffsetForNewRegion(Vector3 offset) 3253 public void OffsetForNewRegion(Vector3 offset)
@@ -2895,7 +3267,7 @@ namespace OpenSim.Region.Framework.Scenes
2895 { 3267 {
2896 SceneObjectPart[] parts = m_parts.GetArray(); 3268 SceneObjectPart[] parts = m_parts.GetArray();
2897 for (int i = 0; i < parts.Length; i++) 3269 for (int i = 0; i < parts.Length; i++)
2898 parts[i].StoreUndoState(); 3270 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2899 3271
2900 m_rootPart.UpdateRotation(rot); 3272 m_rootPart.UpdateRotation(rot);
2901 3273
@@ -2919,7 +3291,7 @@ namespace OpenSim.Region.Framework.Scenes
2919 { 3291 {
2920 SceneObjectPart[] parts = m_parts.GetArray(); 3292 SceneObjectPart[] parts = m_parts.GetArray();
2921 for (int i = 0; i < parts.Length; i++) 3293 for (int i = 0; i < parts.Length; i++)
2922 parts[i].StoreUndoState(); 3294 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2923 3295
2924 m_rootPart.UpdateRotation(rot); 3296 m_rootPart.UpdateRotation(rot);
2925 3297
@@ -2944,10 +3316,9 @@ namespace OpenSim.Region.Framework.Scenes
2944 public void UpdateSingleRotation(Quaternion rot, uint localID) 3316 public void UpdateSingleRotation(Quaternion rot, uint localID)
2945 { 3317 {
2946 SceneObjectPart part = GetChildPart(localID); 3318 SceneObjectPart part = GetChildPart(localID);
2947
2948 SceneObjectPart[] parts = m_parts.GetArray(); 3319 SceneObjectPart[] parts = m_parts.GetArray();
2949 for (int i = 0; i < parts.Length; i++) 3320 for (int i = 0; i < parts.Length; i++)
2950 parts[i].StoreUndoState(); 3321 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2951 3322
2952 if (part != null) 3323 if (part != null)
2953 { 3324 {
@@ -2975,15 +3346,24 @@ namespace OpenSim.Region.Framework.Scenes
2975 if (part.UUID == m_rootPart.UUID) 3346 if (part.UUID == m_rootPart.UUID)
2976 { 3347 {
2977 UpdateRootRotation(rot); 3348 UpdateRootRotation(rot);
2978 AbsolutePosition = pos; 3349 if (!m_rootPart.Undoing)
3350 {
3351 m_rootPart.Undoing = true;
3352 AbsolutePosition = pos;
3353 m_rootPart.Undoing = false;
3354 }
3355 else
3356 {
3357 AbsolutePosition = pos;
3358 }
2979 } 3359 }
2980 else 3360 else
2981 { 3361 {
3362 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2982 part.IgnoreUndoUpdate = true; 3363 part.IgnoreUndoUpdate = true;
2983 part.UpdateRotation(rot); 3364 part.UpdateRotation(rot);
2984 part.OffsetPosition = pos; 3365 part.OffsetPosition = pos;
2985 part.IgnoreUndoUpdate = false; 3366 part.IgnoreUndoUpdate = false;
2986 part.StoreUndoState();
2987 } 3367 }
2988 } 3368 }
2989 } 3369 }
@@ -2997,7 +3377,13 @@ namespace OpenSim.Region.Framework.Scenes
2997 Quaternion axRot = rot; 3377 Quaternion axRot = rot;
2998 Quaternion oldParentRot = m_rootPart.RotationOffset; 3378 Quaternion oldParentRot = m_rootPart.RotationOffset;
2999 3379
3000 m_rootPart.StoreUndoState(); 3380 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3381 bool cancelUndo = false;
3382 if (!m_rootPart.Undoing)
3383 {
3384 m_rootPart.Undoing = true;
3385 cancelUndo = true;
3386 }
3001 m_rootPart.UpdateRotation(rot); 3387 m_rootPart.UpdateRotation(rot);
3002 if (m_rootPart.PhysActor != null) 3388 if (m_rootPart.PhysActor != null)
3003 { 3389 {
@@ -3021,17 +3407,12 @@ namespace OpenSim.Region.Framework.Scenes
3021 newRot *= Quaternion.Inverse(axRot); 3407 newRot *= Quaternion.Inverse(axRot);
3022 prim.RotationOffset = newRot; 3408 prim.RotationOffset = newRot;
3023 prim.ScheduleTerseUpdate(); 3409 prim.ScheduleTerseUpdate();
3410 prim.IgnoreUndoUpdate = false;
3024 } 3411 }
3025 } 3412 }
3026 3413 if (cancelUndo == true)
3027 for (int i = 0; i < parts.Length; i++)
3028 { 3414 {
3029 SceneObjectPart childpart = parts[i]; 3415 m_rootPart.Undoing = false;
3030 if (childpart != m_rootPart)
3031 {
3032 childpart.IgnoreUndoUpdate = false;
3033 childpart.StoreUndoState();
3034 }
3035 } 3416 }
3036 3417
3037 m_rootPart.ScheduleTerseUpdate(); 3418 m_rootPart.ScheduleTerseUpdate();
@@ -3257,7 +3638,6 @@ namespace OpenSim.Region.Framework.Scenes
3257 public float GetMass() 3638 public float GetMass()
3258 { 3639 {
3259 float retmass = 0f; 3640 float retmass = 0f;
3260
3261 SceneObjectPart[] parts = m_parts.GetArray(); 3641 SceneObjectPart[] parts = m_parts.GetArray();
3262 for (int i = 0; i < parts.Length; i++) 3642 for (int i = 0; i < parts.Length; i++)
3263 retmass += parts[i].GetMass(); 3643 retmass += parts[i].GetMass();
@@ -3373,6 +3753,14 @@ namespace OpenSim.Region.Framework.Scenes
3373 SetFromItemID(uuid); 3753 SetFromItemID(uuid);
3374 } 3754 }
3375 3755
3756 public void ResetOwnerChangeFlag()
3757 {
3758 ForEachPart(delegate(SceneObjectPart part)
3759 {
3760 part.ResetOwnerChangeFlag();
3761 });
3762 }
3763
3376 #endregion 3764 #endregion
3377 } 3765 }
3378} 3766}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 6a92378..d4f3dfe 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -61,7 +61,8 @@ namespace OpenSim.Region.Framework.Scenes
61 TELEPORT = 512, 61 TELEPORT = 512,
62 REGION_RESTART = 1024, 62 REGION_RESTART = 1024,
63 MEDIA = 2048, 63 MEDIA = 2048,
64 ANIMATION = 16384 64 ANIMATION = 16384,
65 POSITION = 32768
65 } 66 }
66 67
67 // I don't really know where to put this except here. 68 // I don't really know where to put this except here.
@@ -145,10 +146,10 @@ namespace OpenSim.Region.Framework.Scenes
145 public Vector3 StatusSandboxPos; 146 public Vector3 StatusSandboxPos;
146 147
147 // TODO: This needs to be persisted in next XML version update! 148 // TODO: This needs to be persisted in next XML version update!
148 149 [XmlIgnore]
149 public readonly int[] PayPrice = {-2,-2,-2,-2,-2}; 150 public int[] PayPrice = {-2,-2,-2,-2,-2};
150 151
151 152 [XmlIgnore]
152 public PhysicsActor PhysActor 153 public PhysicsActor PhysActor
153 { 154 {
154 get { return m_physActor; } 155 get { return m_physActor; }
@@ -190,7 +191,15 @@ namespace OpenSim.Region.Framework.Scenes
190 191
191 public UUID FromFolderID; 192 public UUID FromFolderID;
192 193
193 194 // The following two are to hold the attachment data
195 // while an object is inworld
196 [XmlIgnore]
197 public byte AttachPoint = 0;
198
199 [XmlIgnore]
200 public Vector3 AttachOffset = Vector3.Zero;
201
202 [XmlIgnore]
194 public int STATUS_ROTATE_X; 203 public int STATUS_ROTATE_X;
195 204
196 205
@@ -285,6 +294,7 @@ namespace OpenSim.Region.Framework.Scenes
285 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 294 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
286 private Vector3 m_sitTargetPosition; 295 private Vector3 m_sitTargetPosition;
287 private string m_sitAnimation = "SIT"; 296 private string m_sitAnimation = "SIT";
297 private bool m_occupied; // KF if any av is sitting on this prim
288 private string m_text = String.Empty; 298 private string m_text = String.Empty;
289 private string m_touchName = String.Empty; 299 private string m_touchName = String.Empty;
290 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 300 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -374,7 +384,7 @@ namespace OpenSim.Region.Framework.Scenes
374 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 384 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
375 Quaternion rotationOffset, Vector3 offsetPosition) 385 Quaternion rotationOffset, Vector3 offsetPosition)
376 { 386 {
377 m_name = "Primitive"; 387 m_name = "Object";
378 388
379 Rezzed = DateTime.UtcNow; 389 Rezzed = DateTime.UtcNow;
380 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 390 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
@@ -430,7 +440,7 @@ namespace OpenSim.Region.Framework.Scenes
430 private uint _ownerMask = (uint)PermissionMask.All; 440 private uint _ownerMask = (uint)PermissionMask.All;
431 private uint _groupMask = (uint)PermissionMask.None; 441 private uint _groupMask = (uint)PermissionMask.None;
432 private uint _everyoneMask = (uint)PermissionMask.None; 442 private uint _everyoneMask = (uint)PermissionMask.None;
433 private uint _nextOwnerMask = (uint)PermissionMask.All; 443 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
434 private PrimFlags _flags = PrimFlags.None; 444 private PrimFlags _flags = PrimFlags.None;
435 private DateTime m_expires; 445 private DateTime m_expires;
436 private DateTime m_rezzed; 446 private DateTime m_rezzed;
@@ -529,12 +539,16 @@ namespace OpenSim.Region.Framework.Scenes
529 } 539 }
530 540
531 /// <value> 541 /// <value>
532 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 542 /// Get the inventory list
533 /// </value> 543 /// </value>
534 public TaskInventoryDictionary TaskInventory 544 public TaskInventoryDictionary TaskInventory
535 { 545 {
536 get { return m_inventory.Items; } 546 get {
537 set { m_inventory.Items = value; } 547 return m_inventory.Items;
548 }
549 set {
550 m_inventory.Items = value;
551 }
538 } 552 }
539 553
540 /// <summary> 554 /// <summary>
@@ -674,14 +688,12 @@ namespace OpenSim.Region.Framework.Scenes
674 set { m_LoopSoundSlavePrims = value; } 688 set { m_LoopSoundSlavePrims = value; }
675 } 689 }
676 690
677
678 public Byte[] TextureAnimation 691 public Byte[] TextureAnimation
679 { 692 {
680 get { return m_TextureAnimation; } 693 get { return m_TextureAnimation; }
681 set { m_TextureAnimation = value; } 694 set { m_TextureAnimation = value; }
682 } 695 }
683 696
684
685 public Byte[] ParticleSystem 697 public Byte[] ParticleSystem
686 { 698 {
687 get { return m_particleSystem; } 699 get { return m_particleSystem; }
@@ -718,9 +730,11 @@ namespace OpenSim.Region.Framework.Scenes
718 { 730 {
719 // If this is a linkset, we don't want the physics engine mucking up our group position here. 731 // If this is a linkset, we don't want the physics engine mucking up our group position here.
720 PhysicsActor actor = PhysActor; 732 PhysicsActor actor = PhysActor;
721 if (actor != null && _parentID == 0) 733 if (_parentID == 0)
722 { 734 {
723 m_groupPosition = actor.Position; 735 if (actor != null)
736 m_groupPosition = actor.Position;
737 return m_groupPosition;
724 } 738 }
725 739
726 if (IsAttachment) 740 if (IsAttachment)
@@ -730,12 +744,14 @@ namespace OpenSim.Region.Framework.Scenes
730 return sp.AbsolutePosition; 744 return sp.AbsolutePosition;
731 } 745 }
732 746
747 // use root prim's group position. Physics may have updated it
748 if (ParentGroup.RootPart != this)
749 m_groupPosition = ParentGroup.RootPart.GroupPosition;
733 return m_groupPosition; 750 return m_groupPosition;
734 } 751 }
735 set 752 set
736 { 753 {
737 m_groupPosition = value; 754 m_groupPosition = value;
738
739 PhysicsActor actor = PhysActor; 755 PhysicsActor actor = PhysActor;
740 if (actor != null) 756 if (actor != null)
741 { 757 {
@@ -755,25 +771,13 @@ namespace OpenSim.Region.Framework.Scenes
755 771
756 // Tell the physics engines that this prim changed. 772 // Tell the physics engines that this prim changed.
757 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 773 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
774
758 } 775 }
759 catch (Exception e) 776 catch (Exception e)
760 { 777 {
761 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 778 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
762 } 779 }
763 } 780 }
764
765 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
766 if (m_sitTargetAvatar != UUID.Zero)
767 {
768 if (m_parentGroup != null) // TODO can there be a SOP without a SOG?
769 {
770 ScenePresence avatar;
771 if (m_parentGroup.Scene.TryGetScenePresence(m_sitTargetAvatar, out avatar))
772 {
773 avatar.ParentPosition = GetWorldPosition();
774 }
775 }
776 }
777 } 781 }
778 } 782 }
779 783
@@ -782,7 +786,8 @@ namespace OpenSim.Region.Framework.Scenes
782 get { return m_offsetPosition; } 786 get { return m_offsetPosition; }
783 set 787 set
784 { 788 {
785 StoreUndoState(); 789 Vector3 oldpos = m_offsetPosition;
790 StoreUndoState(UndoType.STATE_PRIM_POSITION);
786 m_offsetPosition = value; 791 m_offsetPosition = value;
787 792
788 if (ParentGroup != null && !ParentGroup.IsDeleted) 793 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -796,7 +801,22 @@ namespace OpenSim.Region.Framework.Scenes
796 // Tell the physics engines that this prim changed. 801 // Tell the physics engines that this prim changed.
797 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 802 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
798 } 803 }
804
805 if (!m_parentGroup.m_dupeInProgress)
806 {
807 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
808 foreach (ScenePresence av in avs)
809 {
810 if (av.LinkedPrim == m_uuid)
811 {
812 Vector3 offset = (m_offsetPosition - oldpos);
813 av.OffsetPosition += offset;
814 av.SendAvatarDataToAllAgents();
815 }
816 }
817 }
799 } 818 }
819 TriggerScriptChangedEvent(Changed.POSITION);
800 } 820 }
801 } 821 }
802 822
@@ -838,7 +858,7 @@ namespace OpenSim.Region.Framework.Scenes
838 858
839 set 859 set
840 { 860 {
841 StoreUndoState(); 861 StoreUndoState(UndoType.STATE_PRIM_ROTATION);
842 m_rotationOffset = value; 862 m_rotationOffset = value;
843 863
844 PhysicsActor actor = PhysActor; 864 PhysicsActor actor = PhysActor;
@@ -922,7 +942,16 @@ namespace OpenSim.Region.Framework.Scenes
922 /// <summary></summary> 942 /// <summary></summary>
923 public Vector3 Acceleration 943 public Vector3 Acceleration
924 { 944 {
925 get { return m_acceleration; } 945 get
946 {
947 PhysicsActor actor = PhysActor;
948 if (actor != null)
949 {
950 m_acceleration = actor.Acceleration;
951 }
952 return m_acceleration;
953 }
954
926 set { m_acceleration = value; } 955 set { m_acceleration = value; }
927 } 956 }
928 957
@@ -1013,7 +1042,7 @@ namespace OpenSim.Region.Framework.Scenes
1013 get { return m_shape.Scale; } 1042 get { return m_shape.Scale; }
1014 set 1043 set
1015 { 1044 {
1016 StoreUndoState(); 1045 StoreUndoState(UndoType.STATE_PRIM_SCALE);
1017 if (m_shape != null) 1046 if (m_shape != null)
1018 { 1047 {
1019 m_shape.Scale = value; 1048 m_shape.Scale = value;
@@ -1079,11 +1108,10 @@ namespace OpenSim.Region.Framework.Scenes
1079 1108
1080 public Vector3 AbsolutePosition 1109 public Vector3 AbsolutePosition
1081 { 1110 {
1082 get { 1111 get
1083 if (IsAttachment) 1112 {
1084 return GroupPosition; 1113 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1085 1114 }
1086 return m_offsetPosition + m_groupPosition; }
1087 } 1115 }
1088 1116
1089 public SceneObjectGroup ParentGroup 1117 public SceneObjectGroup ParentGroup
@@ -1242,6 +1270,13 @@ namespace OpenSim.Region.Framework.Scenes
1242 _flags = value; 1270 _flags = value;
1243 } 1271 }
1244 } 1272 }
1273
1274 [XmlIgnore]
1275 public bool IsOccupied // KF If an av is sittingon this prim
1276 {
1277 get { return m_occupied; }
1278 set { m_occupied = value; }
1279 }
1245 1280
1246 1281
1247 public UUID SitTargetAvatar 1282 public UUID SitTargetAvatar
@@ -1317,14 +1352,6 @@ namespace OpenSim.Region.Framework.Scenes
1317 } 1352 }
1318 } 1353 }
1319 1354
1320 /// <summary>
1321 /// Clear all pending updates of parts to clients
1322 /// </summary>
1323 private void ClearUpdateSchedule()
1324 {
1325 m_updateFlag = 0;
1326 }
1327
1328 private void SendObjectPropertiesToClient(UUID AgentID) 1355 private void SendObjectPropertiesToClient(UUID AgentID)
1329 { 1356 {
1330 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1357 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1575,14 +1602,22 @@ namespace OpenSim.Region.Framework.Scenes
1575 // or flexible 1602 // or flexible
1576 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) 1603 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
1577 { 1604 {
1578 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 1605 try
1579 string.Format("{0}/{1}", Name, UUID), 1606 {
1580 Shape, 1607 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1581 AbsolutePosition, 1608 string.Format("{0}/{1}", Name, UUID),
1582 Scale, 1609 Shape,
1583 RotationOffset, 1610 AbsolutePosition,
1584 RigidBody); 1611 Scale,
1585 1612 RotationOffset,
1613 RigidBody);
1614 PhysActor.SetMaterial(Material);
1615 }
1616 catch
1617 {
1618 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
1619 PhysActor = null;
1620 }
1586 // Basic Physics returns null.. joy joy joy. 1621 // Basic Physics returns null.. joy joy joy.
1587 if (PhysActor != null) 1622 if (PhysActor != null)
1588 { 1623 {
@@ -1610,7 +1645,7 @@ namespace OpenSim.Region.Framework.Scenes
1610 { 1645 {
1611 m_redo.Clear(); 1646 m_redo.Clear();
1612 } 1647 }
1613 StoreUndoState(); 1648 StoreUndoState(UndoType.STATE_ALL);
1614 } 1649 }
1615 1650
1616 public byte ConvertScriptUintToByte(uint indata) 1651 public byte ConvertScriptUintToByte(uint indata)
@@ -1679,6 +1714,9 @@ namespace OpenSim.Region.Framework.Scenes
1679 1714
1680 // Move afterwards ResetIDs as it clears the localID 1715 // Move afterwards ResetIDs as it clears the localID
1681 dupe.LocalId = localID; 1716 dupe.LocalId = localID;
1717 if(dupe.PhysActor != null)
1718 dupe.PhysActor.LocalID = localID;
1719
1682 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1720 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1683 dupe._lastOwnerID = OwnerID; 1721 dupe._lastOwnerID = OwnerID;
1684 1722
@@ -1722,7 +1760,7 @@ namespace OpenSim.Region.Framework.Scenes
1722 PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); 1760 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1723 part.Shape = shape; 1761 part.Shape = shape;
1724 1762
1725 part.Name = "Primitive"; 1763 part.Name = "Object";
1726 part._ownerID = UUID.Random(); 1764 part._ownerID = UUID.Random();
1727 1765
1728 return part; 1766 return part;
@@ -2083,12 +2121,17 @@ namespace OpenSim.Region.Framework.Scenes
2083 public Vector3 GetWorldPosition() 2121 public Vector3 GetWorldPosition()
2084 { 2122 {
2085 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2123 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2086
2087 Vector3 axPos = OffsetPosition; 2124 Vector3 axPos = OffsetPosition;
2088
2089 axPos *= parentRot; 2125 axPos *= parentRot;
2090 Vector3 translationOffsetPosition = axPos; 2126 Vector3 translationOffsetPosition = axPos;
2091 return GroupPosition + translationOffsetPosition; 2127 if(_parentID == 0)
2128 {
2129 return GroupPosition;
2130 }
2131 else
2132 {
2133 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2134 }
2092 } 2135 }
2093 2136
2094 /// <summary> 2137 /// <summary>
@@ -2099,7 +2142,7 @@ namespace OpenSim.Region.Framework.Scenes
2099 { 2142 {
2100 Quaternion newRot; 2143 Quaternion newRot;
2101 2144
2102 if (this.LinkNum == 0) 2145 if (this.LinkNum < 2) //KF Single or root prim
2103 { 2146 {
2104 newRot = RotationOffset; 2147 newRot = RotationOffset;
2105 } 2148 }
@@ -2745,17 +2788,18 @@ namespace OpenSim.Region.Framework.Scenes
2745 //Trys to fetch sound id from prim's inventory. 2788 //Trys to fetch sound id from prim's inventory.
2746 //Prim's inventory doesn't support non script items yet 2789 //Prim's inventory doesn't support non script items yet
2747 2790
2748 lock (TaskInventory) 2791 TaskInventory.LockItemsForRead(true);
2792
2793 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2749 { 2794 {
2750 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2795 if (item.Value.Name == sound)
2751 { 2796 {
2752 if (item.Value.Name == sound) 2797 soundID = item.Value.ItemID;
2753 { 2798 break;
2754 soundID = item.Value.ItemID;
2755 break;
2756 }
2757 } 2799 }
2758 } 2800 }
2801
2802 TaskInventory.LockItemsForRead(false);
2759 } 2803 }
2760 2804
2761 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2805 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2815,7 +2859,7 @@ namespace OpenSim.Region.Framework.Scenes
2815 /// <param name="scale"></param> 2859 /// <param name="scale"></param>
2816 public void Resize(Vector3 scale) 2860 public void Resize(Vector3 scale)
2817 { 2861 {
2818 StoreUndoState(); 2862 StoreUndoState(UndoType.STATE_PRIM_SCALE);
2819 m_shape.Scale = scale; 2863 m_shape.Scale = scale;
2820 2864
2821 ParentGroup.HasGroupChanged = true; 2865 ParentGroup.HasGroupChanged = true;
@@ -2824,38 +2868,7 @@ namespace OpenSim.Region.Framework.Scenes
2824 2868
2825 public void RotLookAt(Quaternion target, float strength, float damping) 2869 public void RotLookAt(Quaternion target, float strength, float damping)
2826 { 2870 {
2827 rotLookAt(target, strength, damping); 2871 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2828 }
2829
2830 public void rotLookAt(Quaternion target, float strength, float damping)
2831 {
2832 if (IsAttachment)
2833 {
2834 /*
2835 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2836 if (avatar != null)
2837 {
2838 Rotate the Av?
2839 } */
2840 }
2841 else
2842 {
2843 APIDDamp = damping;
2844 APIDStrength = strength;
2845 APIDTarget = target;
2846 }
2847 }
2848
2849 public void startLookAt(Quaternion rot, float damp, float strength)
2850 {
2851 APIDDamp = damp;
2852 APIDStrength = strength;
2853 APIDTarget = rot;
2854 }
2855
2856 public void stopLookAt()
2857 {
2858 APIDTarget = Quaternion.Identity;
2859 } 2872 }
2860 2873
2861 /// <summary> 2874 /// <summary>
@@ -2867,7 +2880,10 @@ namespace OpenSim.Region.Framework.Scenes
2867 2880
2868 if (m_parentGroup != null) 2881 if (m_parentGroup != null)
2869 { 2882 {
2870 m_parentGroup.QueueForUpdateCheck(); 2883 if (!m_parentGroup.areUpdatesSuspended)
2884 {
2885 m_parentGroup.QueueForUpdateCheck();
2886 }
2871 } 2887 }
2872 2888
2873 int timeNow = Util.UnixTimeSinceEpoch(); 2889 int timeNow = Util.UnixTimeSinceEpoch();
@@ -3084,8 +3100,8 @@ namespace OpenSim.Region.Framework.Scenes
3084 { 3100 {
3085 const float ROTATION_TOLERANCE = 0.01f; 3101 const float ROTATION_TOLERANCE = 0.01f;
3086 const float VELOCITY_TOLERANCE = 0.001f; 3102 const float VELOCITY_TOLERANCE = 0.001f;
3087 const float POSITION_TOLERANCE = 0.05f; 3103 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3088 const int TIME_MS_TOLERANCE = 3000; 3104 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3089 3105
3090 if (m_updateFlag == 1) 3106 if (m_updateFlag == 1)
3091 { 3107 {
@@ -3099,7 +3115,7 @@ namespace OpenSim.Region.Framework.Scenes
3099 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3115 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3100 { 3116 {
3101 AddTerseUpdateToAllAvatars(); 3117 AddTerseUpdateToAllAvatars();
3102 ClearUpdateSchedule(); 3118
3103 3119
3104 // This causes the Scene to 'poll' physical objects every couple of frames 3120 // This causes the Scene to 'poll' physical objects every couple of frames
3105 // bad, so it's been replaced by an event driven method. 3121 // bad, so it's been replaced by an event driven method.
@@ -3117,16 +3133,18 @@ namespace OpenSim.Region.Framework.Scenes
3117 m_lastAngularVelocity = AngularVelocity; 3133 m_lastAngularVelocity = AngularVelocity;
3118 m_lastTerseSent = Environment.TickCount; 3134 m_lastTerseSent = Environment.TickCount;
3119 } 3135 }
3136 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3137 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3120 } 3138 }
3121 else 3139 else
3122 { 3140 {
3123 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3141 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3124 { 3142 {
3125 AddFullUpdateToAllAvatars(); 3143 AddFullUpdateToAllAvatars();
3126 ClearUpdateSchedule(); 3144 m_updateFlag = 0; //Same here
3127 } 3145 }
3128 } 3146 }
3129 ClearUpdateSchedule(); 3147 m_updateFlag = 0;
3130 } 3148 }
3131 3149
3132 /// <summary> 3150 /// <summary>
@@ -3154,17 +3172,16 @@ namespace OpenSim.Region.Framework.Scenes
3154 if (!UUID.TryParse(sound, out soundID)) 3172 if (!UUID.TryParse(sound, out soundID))
3155 { 3173 {
3156 // search sound file from inventory 3174 // search sound file from inventory
3157 lock (TaskInventory) 3175 TaskInventory.LockItemsForRead(true);
3176 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3158 { 3177 {
3159 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3178 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3160 { 3179 {
3161 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3180 soundID = item.Value.ItemID;
3162 { 3181 break;
3163 soundID = item.Value.ItemID;
3164 break;
3165 }
3166 } 3182 }
3167 } 3183 }
3184 TaskInventory.LockItemsForRead(false);
3168 } 3185 }
3169 3186
3170 if (soundID == UUID.Zero) 3187 if (soundID == UUID.Zero)
@@ -3594,7 +3611,7 @@ namespace OpenSim.Region.Framework.Scenes
3594 3611
3595 public void StopLookAt() 3612 public void StopLookAt()
3596 { 3613 {
3597 m_parentGroup.stopLookAt(); 3614 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3598 3615
3599 m_parentGroup.ScheduleGroupForTerseUpdate(); 3616 m_parentGroup.ScheduleGroupForTerseUpdate();
3600 } 3617 }
@@ -3621,10 +3638,9 @@ namespace OpenSim.Region.Framework.Scenes
3621 m_parentGroup.ScheduleGroupForTerseUpdate(); 3638 m_parentGroup.ScheduleGroupForTerseUpdate();
3622 //m_parentGroup.ScheduleGroupForFullUpdate(); 3639 //m_parentGroup.ScheduleGroupForFullUpdate();
3623 } 3640 }
3624 3641 public void StoreUndoState(UndoType type)
3625 public void StoreUndoState()
3626 { 3642 {
3627 if (!Undoing) 3643 if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing))
3628 { 3644 {
3629 if (!IgnoreUndoUpdate) 3645 if (!IgnoreUndoUpdate)
3630 { 3646 {
@@ -3635,17 +3651,25 @@ namespace OpenSim.Region.Framework.Scenes
3635 if (m_undo.Count > 0) 3651 if (m_undo.Count > 0)
3636 { 3652 {
3637 UndoState last = m_undo.Peek(); 3653 UndoState last = m_undo.Peek();
3638 if (last != null) 3654
3639 {
3640 if (last.Compare(this))
3641 return;
3642 }
3643 } 3655 }
3644 3656
3645 if (m_parentGroup.GetSceneMaxUndo() > 0) 3657 if (m_parentGroup.GetSceneMaxUndo() > 0)
3646 { 3658 {
3647 UndoState nUndo = new UndoState(this); 3659 UndoState lastUndo = m_undo.Peek();
3648 3660
3661 UndoState nUndo = new UndoState(this, type);
3662
3663 if (lastUndo != null)
3664 {
3665 TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated);
3666 if (ts.TotalMilliseconds < 500)
3667 {
3668 //Delete the last entry since it was less than 500 milliseconds ago
3669 nUndo.Merge(lastUndo);
3670 m_undo.Pop();
3671 }
3672 }
3649 m_undo.Push(nUndo); 3673 m_undo.Push(nUndo);
3650 } 3674 }
3651 3675
@@ -4122,11 +4146,13 @@ namespace OpenSim.Region.Framework.Scenes
4122 if (m_undo.Count > 0) 4146 if (m_undo.Count > 0)
4123 { 4147 {
4124 UndoState nUndo = null; 4148 UndoState nUndo = null;
4149 UndoState goback = m_undo.Pop();
4125 if (m_parentGroup.GetSceneMaxUndo() > 0) 4150 if (m_parentGroup.GetSceneMaxUndo() > 0)
4126 { 4151 {
4127 nUndo = new UndoState(this); 4152 nUndo = new UndoState(this, goback.Type);
4128 } 4153 }
4129 UndoState goback = m_undo.Pop(); 4154
4155
4130 if (goback != null) 4156 if (goback != null)
4131 { 4157 {
4132 goback.PlaybackState(this); 4158 goback.PlaybackState(this);
@@ -4141,13 +4167,13 @@ namespace OpenSim.Region.Framework.Scenes
4141 { 4167 {
4142 lock (m_redo) 4168 lock (m_redo)
4143 { 4169 {
4170 UndoState gofwd = m_redo.Pop();
4144 if (m_parentGroup.GetSceneMaxUndo() > 0) 4171 if (m_parentGroup.GetSceneMaxUndo() > 0)
4145 { 4172 {
4146 UndoState nUndo = new UndoState(this); 4173 UndoState nUndo = new UndoState(this, gofwd.Type);
4147 4174
4148 m_undo.Push(nUndo); 4175 m_undo.Push(nUndo);
4149 } 4176 }
4150 UndoState gofwd = m_redo.Pop();
4151 if (gofwd != null) 4177 if (gofwd != null)
4152 gofwd.PlayfwdState(this); 4178 gofwd.PlayfwdState(this);
4153 } 4179 }
@@ -4411,6 +4437,7 @@ namespace OpenSim.Region.Framework.Scenes
4411 Scale, 4437 Scale,
4412 RotationOffset, 4438 RotationOffset,
4413 UsePhysics); 4439 UsePhysics);
4440 PhysActor.SetMaterial(Material);
4414 4441
4415 pa = PhysActor; 4442 pa = PhysActor;
4416 if (pa != null) 4443 if (pa != null)
@@ -4596,8 +4623,9 @@ namespace OpenSim.Region.Framework.Scenes
4596 { 4623 {
4597 m_shape.TextureEntry = textureEntry; 4624 m_shape.TextureEntry = textureEntry;
4598 TriggerScriptChangedEvent(Changed.TEXTURE); 4625 TriggerScriptChangedEvent(Changed.TEXTURE);
4599 4626 m_updateFlag = 1;
4600 ParentGroup.HasGroupChanged = true; 4627 ParentGroup.HasGroupChanged = true;
4628
4601 //This is madness.. 4629 //This is madness..
4602 //ParentGroup.ScheduleGroupForFullUpdate(); 4630 //ParentGroup.ScheduleGroupForFullUpdate();
4603 //This is sparta 4631 //This is sparta
@@ -4830,5 +4858,17 @@ namespace OpenSim.Region.Framework.Scenes
4830 Color color = Color; 4858 Color color = Color;
4831 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4859 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4832 } 4860 }
4861
4862 public void ResetOwnerChangeFlag()
4863 {
4864 List<UUID> inv = Inventory.GetInventoryList();
4865
4866 foreach (UUID itemID in inv)
4867 {
4868 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4869 item.OwnerChanged = false;
4870 Inventory.UpdateInventoryItem(item, false, false);
4871 }
4872 }
4833 } 4873 }
4834} 4874}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 67e59c6..7e59b10 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
@@ -120,39 +126,45 @@ namespace OpenSim.Region.Framework.Scenes
120 /// <param name="linkNum">Link number for the part</param> 126 /// <param name="linkNum">Link number for the part</param>
121 public void ResetInventoryIDs() 127 public void ResetInventoryIDs()
122 { 128 {
123 if (null == m_part || null == m_part.ParentGroup) 129 m_items.LockItemsForWrite(true);
124 return; 130
125 131 if (Items.Count == 0)
126 lock (m_items)
127 { 132 {
128 if (0 == m_items.Count) 133 m_items.LockItemsForWrite(false);
129 return; 134 return;
135 }
130 136
131 IList<TaskInventoryItem> items = GetInventoryItems(); 137 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
132 m_items.Clear(); 138 Items.Clear();
133 139
134 foreach (TaskInventoryItem item in items) 140 foreach (TaskInventoryItem item in items)
135 { 141 {
136 item.ResetIDs(m_part.UUID); 142 item.ResetIDs(m_part.UUID);
137 m_items.Add(item.ItemID, item); 143 Items.Add(item.ItemID, item);
138 }
139 } 144 }
145 m_items.LockItemsForWrite(false);
140 } 146 }
141 147
142 public void ResetObjectID() 148 public void ResetObjectID()
143 { 149 {
144 lock (Items) 150 m_items.LockItemsForWrite(true);
151
152 if (Items.Count == 0)
145 { 153 {
146 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 154 m_items.LockItemsForWrite(false);
147 Items.Clear(); 155 return;
148
149 foreach (TaskInventoryItem item in items)
150 {
151 item.ParentPartID = m_part.UUID;
152 item.ParentID = m_part.UUID;
153 Items.Add(item.ItemID, item);
154 }
155 } 156 }
157
158 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
159 Items.Clear();
160
161 foreach (TaskInventoryItem item in items)
162 {
163 item.ParentPartID = m_part.UUID;
164 item.ParentID = m_part.UUID;
165 Items.Add(item.ItemID, item);
166 }
167 m_items.LockItemsForWrite(false);
156 } 168 }
157 169
158 /// <summary> 170 /// <summary>
@@ -161,12 +173,11 @@ namespace OpenSim.Region.Framework.Scenes
161 /// <param name="ownerId"></param> 173 /// <param name="ownerId"></param>
162 public void ChangeInventoryOwner(UUID ownerId) 174 public void ChangeInventoryOwner(UUID ownerId)
163 { 175 {
164 lock (Items) 176 m_items.LockItemsForWrite(true);
177 if (0 == Items.Count)
165 { 178 {
166 if (0 == Items.Count) 179 m_items.LockItemsForWrite(false);
167 { 180 return;
168 return;
169 }
170 } 181 }
171 182
172 HasInventoryChanged = true; 183 HasInventoryChanged = true;
@@ -182,6 +193,7 @@ namespace OpenSim.Region.Framework.Scenes
182 item.PermsGranter = UUID.Zero; 193 item.PermsGranter = UUID.Zero;
183 } 194 }
184 } 195 }
196 m_items.LockItemsForWrite(false);
185 } 197 }
186 198
187 /// <summary> 199 /// <summary>
@@ -190,12 +202,11 @@ namespace OpenSim.Region.Framework.Scenes
190 /// <param name="groupID"></param> 202 /// <param name="groupID"></param>
191 public void ChangeInventoryGroup(UUID groupID) 203 public void ChangeInventoryGroup(UUID groupID)
192 { 204 {
193 lock (Items) 205 m_items.LockItemsForWrite(true);
206 if (0 == Items.Count)
194 { 207 {
195 if (0 == Items.Count) 208 m_items.LockItemsForWrite(false);
196 { 209 return;
197 return;
198 }
199 } 210 }
200 211
201 // Don't let this set the HasGroupChanged flag for attachments 212 // Don't let this set the HasGroupChanged flag for attachments
@@ -207,12 +218,45 @@ namespace OpenSim.Region.Framework.Scenes
207 m_part.ParentGroup.HasGroupChanged = true; 218 m_part.ParentGroup.HasGroupChanged = true;
208 } 219 }
209 220
210 List<TaskInventoryItem> items = GetInventoryItems(); 221 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
211 foreach (TaskInventoryItem item in items) 222 foreach (TaskInventoryItem item in items)
212 { 223 {
213 if (groupID != item.GroupID) 224 if (groupID != item.GroupID)
225 {
214 item.GroupID = groupID; 226 item.GroupID = groupID;
227 }
215 } 228 }
229 m_items.LockItemsForWrite(false);
230 }
231
232 private void QueryScriptStates()
233 {
234 if (m_part == null || m_part.ParentGroup == null)
235 return;
236
237 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
238 if (engines == null) // No engine at all
239 return;
240
241 Items.LockItemsForRead(true);
242 foreach (TaskInventoryItem item in Items.Values)
243 {
244 if (item.InvType == (int)InventoryType.LSL)
245 {
246 foreach (IScriptModule e in engines)
247 {
248 bool running;
249
250 if (e.HasScript(item.ItemID, out running))
251 {
252 item.ScriptRunning = running;
253 break;
254 }
255 }
256 }
257 }
258
259 Items.LockItemsForRead(false);
216 } 260 }
217 261
218 /// <summary> 262 /// <summary>
@@ -220,9 +264,14 @@ namespace OpenSim.Region.Framework.Scenes
220 /// </summary> 264 /// </summary>
221 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 265 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
222 { 266 {
223 List<TaskInventoryItem> scripts = GetInventoryScripts(); 267 Items.LockItemsForRead(true);
224 foreach (TaskInventoryItem item in scripts) 268 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
225 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 269 Items.LockItemsForRead(false);
270 foreach (TaskInventoryItem item in items)
271 {
272 if ((int)InventoryType.LSL == item.InvType)
273 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
274 }
226 } 275 }
227 276
228 public ArrayList GetScriptErrors(UUID itemID) 277 public ArrayList GetScriptErrors(UUID itemID)
@@ -255,9 +304,18 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </param> 304 /// </param>
256 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 305 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
257 { 306 {
258 List<TaskInventoryItem> scripts = GetInventoryScripts(); 307 Items.LockItemsForRead(true);
259 foreach (TaskInventoryItem item in scripts) 308 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 309 Items.LockItemsForRead(false);
310
311 foreach (TaskInventoryItem item in items)
312 {
313 if ((int)InventoryType.LSL == item.InvType)
314 {
315 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
316 m_part.RemoveScriptEvents(item.ItemID);
317 }
318 }
261 } 319 }
262 320
263 /// <summary> 321 /// <summary>
@@ -273,7 +331,10 @@ namespace OpenSim.Region.Framework.Scenes
273 // item.Name, item.ItemID, Name, UUID); 331 // item.Name, item.ItemID, Name, UUID);
274 332
275 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 333 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
334 {
335 StoreScriptError(item.ItemID, "no permission");
276 return; 336 return;
337 }
277 338
278 m_part.AddFlag(PrimFlags.Scripted); 339 m_part.AddFlag(PrimFlags.Scripted);
279 340
@@ -282,14 +343,13 @@ namespace OpenSim.Region.Framework.Scenes
282 if (stateSource == 2 && // Prim crossing 343 if (stateSource == 2 && // Prim crossing
283 m_part.ParentGroup.Scene.m_trustBinaries) 344 m_part.ParentGroup.Scene.m_trustBinaries)
284 { 345 {
285 lock (m_items) 346 m_items.LockItemsForWrite(true);
286 { 347 m_items[item.ItemID].PermsMask = 0;
287 m_items[item.ItemID].PermsMask = 0; 348 m_items[item.ItemID].PermsGranter = UUID.Zero;
288 m_items[item.ItemID].PermsGranter = UUID.Zero; 349 m_items.LockItemsForWrite(false);
289 }
290
291 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 350 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
292 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 351 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
352 StoreScriptErrors(item.ItemID, null);
293 m_part.ParentGroup.AddActiveScriptCount(1); 353 m_part.ParentGroup.AddActiveScriptCount(1);
294 m_part.ScheduleFullUpdate(); 354 m_part.ScheduleFullUpdate();
295 return; 355 return;
@@ -298,6 +358,8 @@ namespace OpenSim.Region.Framework.Scenes
298 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 358 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
299 if (null == asset) 359 if (null == asset)
300 { 360 {
361 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
362 StoreScriptError(item.ItemID, msg);
301 m_log.ErrorFormat( 363 m_log.ErrorFormat(
302 "[PRIM INVENTORY]: " + 364 "[PRIM INVENTORY]: " +
303 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 365 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -309,15 +371,20 @@ namespace OpenSim.Region.Framework.Scenes
309 if (m_part.ParentGroup.m_savedScriptState != null) 371 if (m_part.ParentGroup.m_savedScriptState != null)
310 RestoreSavedScriptState(item.OldItemID, item.ItemID); 372 RestoreSavedScriptState(item.OldItemID, item.ItemID);
311 373
312 lock (m_items) 374 m_items.LockItemsForWrite(true);
313 { 375
314 m_items[item.ItemID].PermsMask = 0; 376 m_items[item.ItemID].PermsMask = 0;
315 m_items[item.ItemID].PermsGranter = UUID.Zero; 377 m_items[item.ItemID].PermsGranter = UUID.Zero;
316 } 378
379 m_items.LockItemsForWrite(false);
317 380
318 string script = Utils.BytesToString(asset.Data); 381 string script = Utils.BytesToString(asset.Data);
319 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 382 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
320 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 383 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
384 StoreScriptErrors(item.ItemID, null);
385 if (!item.ScriptRunning)
386 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
387 m_part.LocalId, item.ItemID);
321 m_part.ParentGroup.AddActiveScriptCount(1); 388 m_part.ParentGroup.AddActiveScriptCount(1);
322 m_part.ScheduleFullUpdate(); 389 m_part.ScheduleFullUpdate();
323 } 390 }
@@ -381,21 +448,145 @@ namespace OpenSim.Region.Framework.Scenes
381 448
382 /// <summary> 449 /// <summary>
383 /// Start a script which is in this prim's inventory. 450 /// Start a script which is in this prim's inventory.
451 /// Some processing may occur in the background, but this routine returns asap.
384 /// </summary> 452 /// </summary>
385 /// <param name="itemId"> 453 /// <param name="itemId">
386 /// A <see cref="UUID"/> 454 /// A <see cref="UUID"/>
387 /// </param> 455 /// </param>
388 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 456 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
389 { 457 {
390 TaskInventoryItem item = GetInventoryItem(itemId); 458 lock (m_scriptErrors)
391 if (item != null) 459 {
392 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 460 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
461 m_scriptErrors.Remove(itemId);
462 }
463 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
464 }
465
466 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
467 {
468 m_items.LockItemsForRead(true);
469 if (m_items.ContainsKey(itemId))
470 {
471 if (m_items.ContainsKey(itemId))
472 {
473 m_items.LockItemsForRead(false);
474 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
475 }
476 else
477 {
478 m_items.LockItemsForRead(false);
479 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
480 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
481 StoreScriptError(itemId, msg);
482 m_log.ErrorFormat(
483 "[PRIM INVENTORY]: " +
484 "Couldn't start script with ID {0} since it {1}", itemId, msg);
485 }
486 }
393 else 487 else
488 {
489 m_items.LockItemsForRead(false);
490 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
491 StoreScriptError(itemId, msg);
394 m_log.ErrorFormat( 492 m_log.ErrorFormat(
395 "[PRIM INVENTORY]: " + 493 "[PRIM INVENTORY]: " +
396 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 494 "Couldn't start script with ID {0} since it {1}", itemId, msg);
397 itemId, m_part.Name, m_part.UUID, 495 }
398 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 496
497 }
498
499 /// <summary>
500 /// Start a script which is in this prim's inventory and return any compilation error messages.
501 /// </summary>
502 /// <param name="itemId">
503 /// A <see cref="UUID"/>
504 /// </param>
505 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
506 {
507 ArrayList errors;
508
509 // Indicate to CreateScriptInstanceInternal() we want it to
510 // post any compilation/loading error messages
511 lock (m_scriptErrors)
512 {
513 m_scriptErrors[itemId] = null;
514 }
515
516 // Perform compilation/loading
517 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
518
519 // Wait for and retrieve any errors
520 lock (m_scriptErrors)
521 {
522 while ((errors = m_scriptErrors[itemId]) == null)
523 {
524 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
525 {
526 m_log.ErrorFormat(
527 "[PRIM INVENTORY]: " +
528 "timedout waiting for script {0} errors", itemId);
529 errors = m_scriptErrors[itemId];
530 if (errors == null)
531 {
532 errors = new ArrayList(1);
533 errors.Add("timedout waiting for errors");
534 }
535 break;
536 }
537 }
538 m_scriptErrors.Remove(itemId);
539 }
540 return errors;
541 }
542
543 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
544 private void StoreScriptErrors(UUID itemId, ArrayList errors)
545 {
546 lock (m_scriptErrors)
547 {
548 // If compilation/loading initiated via CreateScriptInstance(),
549 // it does not want the errors, so just get out
550 if (!m_scriptErrors.ContainsKey(itemId))
551 {
552 return;
553 }
554
555 // Initiated via CreateScriptInstanceEr(), if we know what the
556 // errors are, save them and wake CreateScriptInstanceEr().
557 if (errors != null)
558 {
559 m_scriptErrors[itemId] = errors;
560 System.Threading.Monitor.PulseAll(m_scriptErrors);
561 return;
562 }
563 }
564
565 // Initiated via CreateScriptInstanceEr() but we don't know what
566 // the errors are yet, so retrieve them from the script engine.
567 // This may involve some waiting internal to GetScriptErrors().
568 errors = GetScriptErrors(itemId);
569
570 // Get a default non-null value to indicate success.
571 if (errors == null)
572 {
573 errors = new ArrayList();
574 }
575
576 // Post to CreateScriptInstanceEr() and wake it up
577 lock (m_scriptErrors)
578 {
579 m_scriptErrors[itemId] = errors;
580 System.Threading.Monitor.PulseAll(m_scriptErrors);
581 }
582 }
583
584 // Like StoreScriptErrors(), but just posts a single string message
585 private void StoreScriptError(UUID itemId, string message)
586 {
587 ArrayList errors = new ArrayList(1);
588 errors.Add(message);
589 StoreScriptErrors(itemId, errors);
399 } 590 }
400 591
401 /// <summary> 592 /// <summary>
@@ -408,15 +599,7 @@ namespace OpenSim.Region.Framework.Scenes
408 /// </param> 599 /// </param>
409 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 600 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
410 { 601 {
411 bool scriptPresent = false; 602 if (m_items.ContainsKey(itemId))
412
413 lock (m_items)
414 {
415 if (m_items.ContainsKey(itemId))
416 scriptPresent = true;
417 }
418
419 if (scriptPresent)
420 { 603 {
421 if (!sceneObjectBeingDeleted) 604 if (!sceneObjectBeingDeleted)
422 m_part.RemoveScriptEvents(itemId); 605 m_part.RemoveScriptEvents(itemId);
@@ -441,14 +624,16 @@ namespace OpenSim.Region.Framework.Scenes
441 /// <returns></returns> 624 /// <returns></returns>
442 private bool InventoryContainsName(string name) 625 private bool InventoryContainsName(string name)
443 { 626 {
444 lock (m_items) 627 m_items.LockItemsForRead(true);
628 foreach (TaskInventoryItem item in m_items.Values)
445 { 629 {
446 foreach (TaskInventoryItem item in m_items.Values) 630 if (item.Name == name)
447 { 631 {
448 if (item.Name == name) 632 m_items.LockItemsForRead(false);
449 return true; 633 return true;
450 } 634 }
451 } 635 }
636 m_items.LockItemsForRead(false);
452 return false; 637 return false;
453 } 638 }
454 639
@@ -490,8 +675,9 @@ namespace OpenSim.Region.Framework.Scenes
490 /// <param name="item"></param> 675 /// <param name="item"></param>
491 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 676 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
492 { 677 {
493 List<TaskInventoryItem> il = GetInventoryItems(); 678 m_items.LockItemsForRead(true);
494 679 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
680 m_items.LockItemsForRead(false);
495 foreach (TaskInventoryItem i in il) 681 foreach (TaskInventoryItem i in il)
496 { 682 {
497 if (i.Name == item.Name) 683 if (i.Name == item.Name)
@@ -529,14 +715,14 @@ namespace OpenSim.Region.Framework.Scenes
529 item.Name = name; 715 item.Name = name;
530 item.GroupID = m_part.GroupID; 716 item.GroupID = m_part.GroupID;
531 717
532 lock (m_items) 718 m_items.LockItemsForWrite(true);
533 m_items.Add(item.ItemID, item); 719 m_items.Add(item.ItemID, item);
534 720 m_items.LockItemsForWrite(false);
535 if (allowedDrop) 721 if (allowedDrop)
536 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 722 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
537 else 723 else
538 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 724 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
539 725
540 m_inventorySerial++; 726 m_inventorySerial++;
541 //m_inventorySerial += 2; 727 //m_inventorySerial += 2;
542 HasInventoryChanged = true; 728 HasInventoryChanged = true;
@@ -552,15 +738,15 @@ namespace OpenSim.Region.Framework.Scenes
552 /// <param name="items"></param> 738 /// <param name="items"></param>
553 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 739 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
554 { 740 {
555 lock (m_items) 741 m_items.LockItemsForWrite(true);
742 foreach (TaskInventoryItem item in items)
556 { 743 {
557 foreach (TaskInventoryItem item in items) 744 m_items.Add(item.ItemID, item);
558 { 745// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
559 m_items.Add(item.ItemID, item);
560// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
561 }
562 m_inventorySerial++;
563 } 746 }
747 m_items.LockItemsForWrite(false);
748
749 m_inventorySerial++;
564 } 750 }
565 751
566 /// <summary> 752 /// <summary>
@@ -571,10 +757,9 @@ namespace OpenSim.Region.Framework.Scenes
571 public TaskInventoryItem GetInventoryItem(UUID itemId) 757 public TaskInventoryItem GetInventoryItem(UUID itemId)
572 { 758 {
573 TaskInventoryItem item; 759 TaskInventoryItem item;
574 760 m_items.LockItemsForRead(true);
575 lock (m_items) 761 m_items.TryGetValue(itemId, out item);
576 m_items.TryGetValue(itemId, out item); 762 m_items.LockItemsForRead(false);
577
578 return item; 763 return item;
579 } 764 }
580 765
@@ -590,15 +775,16 @@ namespace OpenSim.Region.Framework.Scenes
590 { 775 {
591 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 776 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
592 777
593 lock (m_items) 778 m_items.LockItemsForRead(true);
779
780 foreach (TaskInventoryItem item in m_items.Values)
594 { 781 {
595 foreach (TaskInventoryItem item in m_items.Values) 782 if (item.Name == name)
596 { 783 items.Add(item);
597 if (item.Name == name)
598 items.Add(item);
599 }
600 } 784 }
601 785
786 m_items.LockItemsForRead(false);
787
602 return items; 788 return items;
603 } 789 }
604 790
@@ -691,9 +877,9 @@ namespace OpenSim.Region.Framework.Scenes
691 877
692 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 878 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
693 { 879 {
694 TaskInventoryItem it = GetInventoryItem(item.ItemID); 880 m_items.LockItemsForWrite(true);
695 if (it != null)
696 881
882 if (m_items.ContainsKey(item.ItemID))
697 { 883 {
698 item.ParentID = m_part.UUID; 884 item.ParentID = m_part.UUID;
699 item.ParentPartID = m_part.UUID; 885 item.ParentPartID = m_part.UUID;
@@ -704,14 +890,10 @@ namespace OpenSim.Region.Framework.Scenes
704 item.GroupID = m_part.GroupID; 890 item.GroupID = m_part.GroupID;
705 891
706 if (item.AssetID == UUID.Zero) 892 if (item.AssetID == UUID.Zero)
707 item.AssetID = it.AssetID; 893 item.AssetID = m_items[item.ItemID].AssetID;
708
709 lock (m_items)
710 {
711 m_items[item.ItemID] = item;
712 m_inventorySerial++;
713 }
714 894
895 m_items[item.ItemID] = item;
896 m_inventorySerial++;
715 if (fireScriptEvents) 897 if (fireScriptEvents)
716 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 898 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
717 if (considerChanged) 899 if (considerChanged)
@@ -719,6 +901,7 @@ namespace OpenSim.Region.Framework.Scenes
719 HasInventoryChanged = true; 901 HasInventoryChanged = true;
720 m_part.ParentGroup.HasGroupChanged = true; 902 m_part.ParentGroup.HasGroupChanged = true;
721 } 903 }
904 m_items.LockItemsForWrite(false);
722 return true; 905 return true;
723 } 906 }
724 else 907 else
@@ -729,8 +912,9 @@ namespace OpenSim.Region.Framework.Scenes
729 item.ItemID, m_part.Name, m_part.UUID, 912 item.ItemID, m_part.Name, m_part.UUID,
730 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 913 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
731 } 914 }
732 return false; 915 m_items.LockItemsForWrite(false);
733 916
917 return false;
734 } 918 }
735 919
736 /// <summary> 920 /// <summary>
@@ -741,107 +925,68 @@ namespace OpenSim.Region.Framework.Scenes
741 /// in this prim's inventory.</returns> 925 /// in this prim's inventory.</returns>
742 public int RemoveInventoryItem(UUID itemID) 926 public int RemoveInventoryItem(UUID itemID)
743 { 927 {
744 TaskInventoryItem item = GetInventoryItem(itemID); 928 m_items.LockItemsForRead(true);
745 if (item != null) 929
930 if (m_items.ContainsKey(itemID))
746 { 931 {
747 int type = m_items[itemID].InvType; 932 int type = m_items[itemID].InvType;
933 m_items.LockItemsForRead(false);
748 if (type == 10) // Script 934 if (type == 10) // Script
749 { 935 {
750 m_part.RemoveScriptEvents(itemID);
751 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 936 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
752 } 937 }
938 m_items.LockItemsForWrite(true);
753 m_items.Remove(itemID); 939 m_items.Remove(itemID);
940 m_items.LockItemsForWrite(false);
754 m_inventorySerial++; 941 m_inventorySerial++;
755 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 942 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
756 943
757 HasInventoryChanged = true; 944 HasInventoryChanged = true;
758 m_part.ParentGroup.HasGroupChanged = true; 945 m_part.ParentGroup.HasGroupChanged = true;
759 946
760 if (!ContainsScripts()) 947 int scriptcount = 0;
948 m_items.LockItemsForRead(true);
949 foreach (TaskInventoryItem item in m_items.Values)
950 {
951 if (item.Type == 10)
952 {
953 scriptcount++;
954 }
955 }
956 m_items.LockItemsForRead(false);
957
958
959 if (scriptcount <= 0)
960 {
761 m_part.RemFlag(PrimFlags.Scripted); 961 m_part.RemFlag(PrimFlags.Scripted);
962 }
762 963
763 m_part.ScheduleFullUpdate(); 964 m_part.ScheduleFullUpdate();
764 965
765 return type; 966 return type;
766
767 } 967 }
768 else 968 else
769 { 969 {
970 m_items.LockItemsForRead(false);
770 m_log.ErrorFormat( 971 m_log.ErrorFormat(
771 "[PRIM INVENTORY]: " + 972 "[PRIM INVENTORY]: " +
772 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 973 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
773 itemID, m_part.Name, m_part.UUID, 974 itemID, m_part.Name, m_part.UUID);
774 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
775 } 975 }
776 976
777 return -1; 977 return -1;
778 } 978 }
779 979
780 private bool CreateInventoryFile() 980 private bool CreateInventoryFileName()
781 { 981 {
782 if (m_inventoryFileName == String.Empty || 982 if (m_inventoryFileName == String.Empty ||
783 m_inventoryFileNameSerial < m_inventorySerial) 983 m_inventoryFileNameSerial < m_inventorySerial)
784 { 984 {
785 // Something changed, we need to create a new file
786 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 985 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
787 m_inventoryFileNameSerial = m_inventorySerial; 986 m_inventoryFileNameSerial = m_inventorySerial;
788
789 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
790
791 lock (m_items)
792 {
793 foreach (TaskInventoryItem item in m_items.Values)
794 {
795 UUID ownerID = item.OwnerID;
796 uint everyoneMask = 0;
797 uint baseMask = item.BasePermissions;
798 uint ownerMask = item.CurrentPermissions;
799 uint groupMask = item.GroupPermissions;
800
801 invString.AddItemStart();
802 invString.AddNameValueLine("item_id", item.ItemID.ToString());
803 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
804
805 invString.AddPermissionsStart();
806
807 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
808 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
809 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
810 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
811 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
812
813 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
814 invString.AddNameValueLine("owner_id", ownerID.ToString());
815
816 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
817
818 invString.AddNameValueLine("group_id", item.GroupID.ToString());
819 invString.AddSectionEnd();
820
821 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
822 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
823 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
824 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
825
826 invString.AddSaleStart();
827 invString.AddNameValueLine("sale_type", "not");
828 invString.AddNameValueLine("sale_price", "0");
829 invString.AddSectionEnd();
830
831 invString.AddNameValueLine("name", item.Name + "|");
832 invString.AddNameValueLine("desc", item.Description + "|");
833
834 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
835 invString.AddSectionEnd();
836 }
837 }
838
839 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
840
841 return true; 987 return true;
842 } 988 }
843 989
844 // No need to recreate, the existing file is fine
845 return false; 990 return false;
846 } 991 }
847 992
@@ -851,26 +996,99 @@ namespace OpenSim.Region.Framework.Scenes
851 /// <param name="xferManager"></param> 996 /// <param name="xferManager"></param>
852 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 997 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
853 { 998 {
854 CreateInventoryFile(); 999 bool changed = CreateInventoryFileName();
1000
1001 bool includeAssets = false;
1002 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1003 includeAssets = true;
1004
1005 if (m_inventoryPrivileged != includeAssets)
1006 changed = true;
1007
1008 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1009
1010 Items.LockItemsForRead(true);
855 1011
856 if (m_inventorySerial == 0) // No inventory 1012 if (m_inventorySerial == 0) // No inventory
857 { 1013 {
858 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1014 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1015 Items.LockItemsForRead(false);
859 return; 1016 return;
860 } 1017 }
861 1018
862 // In principle, we should only do the rest if the inventory changed; 1019 if (!changed)
863 // by sending m_inventorySerial to the client, it ought to know 1020 {
864 // that nothing changed and that it doesn't need to request the file. 1021 if (m_inventoryFileData.Length > 2)
865 // Unfortunately, it doesn't look like the client optimizes this; 1022 {
866 // the client seems to always come back and request the Xfer, 1023 xferManager.AddNewFile(m_inventoryFileName,
867 // no matter what value m_inventorySerial has. 1024 m_inventoryFileData);
1025 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1026 Util.StringToBytes256(m_inventoryFileName));
1027
1028 Items.LockItemsForRead(false);
1029 return;
1030 }
1031 }
1032
1033 m_inventoryPrivileged = includeAssets;
1034
1035 foreach (TaskInventoryItem item in m_items.Values)
1036 {
1037 UUID ownerID = item.OwnerID;
1038 uint everyoneMask = 0;
1039 uint baseMask = item.BasePermissions;
1040 uint ownerMask = item.CurrentPermissions;
1041 uint groupMask = item.GroupPermissions;
1042
1043 invString.AddItemStart();
1044 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1045 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1046
1047 invString.AddPermissionsStart();
1048
1049 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1050 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1051 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1052 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1053 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1054
1055 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1056 invString.AddNameValueLine("owner_id", ownerID.ToString());
1057
1058 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1059
1060 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1061 invString.AddSectionEnd();
1062
1063 if (includeAssets)
1064 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1065 else
1066 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1067 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
1068 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
1069 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1070
1071 invString.AddSaleStart();
1072 invString.AddNameValueLine("sale_type", "not");
1073 invString.AddNameValueLine("sale_price", "0");
1074 invString.AddSectionEnd();
1075
1076 invString.AddNameValueLine("name", item.Name + "|");
1077 invString.AddNameValueLine("desc", item.Description + "|");
1078
1079 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1080 invString.AddSectionEnd();
1081 }
1082
1083 Items.LockItemsForRead(false);
1084
1085 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
868 1086
869 if (m_inventoryFileData.Length > 2) 1087 if (m_inventoryFileData.Length > 2)
870 // Add the file for Xfer 1088 {
871 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 1089 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1090 }
872 1091
873 // Tell the client we're ready to Xfer the file
874 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, 1092 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
875 Util.StringToBytes256(m_inventoryFileName)); 1093 Util.StringToBytes256(m_inventoryFileName));
876 } 1094 }
@@ -883,10 +1101,11 @@ namespace OpenSim.Region.Framework.Scenes
883 { 1101 {
884 if (HasInventoryChanged) 1102 if (HasInventoryChanged)
885 { 1103 {
886 HasInventoryChanged = false; 1104 Items.LockItemsForRead(true);
887 List<TaskInventoryItem> items = GetInventoryItems(); 1105 datastore.StorePrimInventory(m_part.UUID, Items.Values);
888 datastore.StorePrimInventory(m_part.UUID, items); 1106 Items.LockItemsForRead(false);
889 1107
1108 HasInventoryChanged = false;
890 } 1109 }
891 } 1110 }
892 1111
@@ -953,82 +1172,63 @@ namespace OpenSim.Region.Framework.Scenes
953 { 1172 {
954 uint mask=0x7fffffff; 1173 uint mask=0x7fffffff;
955 1174
956 lock (m_items) 1175 foreach (TaskInventoryItem item in m_items.Values)
957 { 1176 {
958 foreach (TaskInventoryItem item in m_items.Values) 1177 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1178 mask &= ~((uint)PermissionMask.Copy >> 13);
1179 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1180 mask &= ~((uint)PermissionMask.Transfer >> 13);
1181 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1182 mask &= ~((uint)PermissionMask.Modify >> 13);
1183
1184 if (item.InvType == (int)InventoryType.Object)
959 { 1185 {
960 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1186 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
961 mask &= ~((uint)PermissionMask.Copy >> 13); 1187 mask &= ~((uint)PermissionMask.Copy >> 13);
962 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1188 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
963 mask &= ~((uint)PermissionMask.Transfer >> 13); 1189 mask &= ~((uint)PermissionMask.Transfer >> 13);
964 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1190 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
965 mask &= ~((uint)PermissionMask.Modify >> 13); 1191 mask &= ~((uint)PermissionMask.Modify >> 13);
966
967 if (item.InvType != (int)InventoryType.Object)
968 {
969 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
970 mask &= ~((uint)PermissionMask.Copy >> 13);
971 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
972 mask &= ~((uint)PermissionMask.Transfer >> 13);
973 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
974 mask &= ~((uint)PermissionMask.Modify >> 13);
975 }
976 else
977 {
978 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
979 mask &= ~((uint)PermissionMask.Copy >> 13);
980 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
981 mask &= ~((uint)PermissionMask.Transfer >> 13);
982 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
983 mask &= ~((uint)PermissionMask.Modify >> 13);
984 }
985
986 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
987 mask &= ~(uint)PermissionMask.Copy;
988 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
989 mask &= ~(uint)PermissionMask.Transfer;
990 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
991 mask &= ~(uint)PermissionMask.Modify;
992 } 1192 }
1193
1194 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1195 mask &= ~(uint)PermissionMask.Copy;
1196 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1197 mask &= ~(uint)PermissionMask.Transfer;
1198 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1199 mask &= ~(uint)PermissionMask.Modify;
993 } 1200 }
994
995 return mask; 1201 return mask;
996 } 1202 }
997 1203
998 public void ApplyNextOwnerPermissions() 1204 public void ApplyNextOwnerPermissions()
999 { 1205 {
1000 lock (m_items) 1206 foreach (TaskInventoryItem item in m_items.Values)
1001 { 1207 {
1002 foreach (TaskInventoryItem item in m_items.Values) 1208 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1003 { 1209 {
1004 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1210 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1005 { 1211 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1006 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1212 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1007 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1213 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1008 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1214 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1009 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1215 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1010 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1011 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1012 }
1013 item.CurrentPermissions &= item.NextPermissions;
1014 item.BasePermissions &= item.NextPermissions;
1015 item.EveryonePermissions &= item.NextPermissions;
1016 item.OwnerChanged = true;
1017 item.PermsMask = 0;
1018 item.PermsGranter = UUID.Zero;
1019 } 1216 }
1217 item.OwnerChanged = true;
1218 item.CurrentPermissions &= item.NextPermissions;
1219 item.BasePermissions &= item.NextPermissions;
1220 item.EveryonePermissions &= item.NextPermissions;
1221 item.PermsMask = 0;
1222 item.PermsGranter = UUID.Zero;
1020 } 1223 }
1021 } 1224 }
1022 1225
1023 public void ApplyGodPermissions(uint perms) 1226 public void ApplyGodPermissions(uint perms)
1024 { 1227 {
1025 lock (m_items) 1228 foreach (TaskInventoryItem item in m_items.Values)
1026 { 1229 {
1027 foreach (TaskInventoryItem item in m_items.Values) 1230 item.CurrentPermissions = perms;
1028 { 1231 item.BasePermissions = perms;
1029 item.CurrentPermissions = perms;
1030 item.BasePermissions = perms;
1031 }
1032 } 1232 }
1033 m_inventorySerial++; 1233 m_inventorySerial++;
1034 HasInventoryChanged = true; 1234 HasInventoryChanged = true;
@@ -1036,17 +1236,13 @@ namespace OpenSim.Region.Framework.Scenes
1036 1236
1037 public bool ContainsScripts() 1237 public bool ContainsScripts()
1038 { 1238 {
1039 lock (m_items) 1239 foreach (TaskInventoryItem item in m_items.Values)
1040 { 1240 {
1041 foreach (TaskInventoryItem item in m_items.Values) 1241 if (item.InvType == (int)InventoryType.LSL)
1042 { 1242 {
1043 if (item.InvType == (int)InventoryType.LSL) 1243 return true;
1044 {
1045 return true;
1046 }
1047 } 1244 }
1048 } 1245 }
1049
1050 return false; 1246 return false;
1051 } 1247 }
1052 1248
@@ -1054,11 +1250,8 @@ namespace OpenSim.Region.Framework.Scenes
1054 { 1250 {
1055 List<UUID> ret = new List<UUID>(); 1251 List<UUID> ret = new List<UUID>();
1056 1252
1057 lock (m_items) 1253 foreach (TaskInventoryItem item in m_items.Values)
1058 { 1254 ret.Add(item.ItemID);
1059 foreach (TaskInventoryItem item in m_items.Values)
1060 ret.Add(item.ItemID);
1061 }
1062 1255
1063 return ret; 1256 return ret;
1064 } 1257 }
@@ -1089,31 +1282,46 @@ namespace OpenSim.Region.Framework.Scenes
1089 1282
1090 public Dictionary<UUID, string> GetScriptStates() 1283 public Dictionary<UUID, string> GetScriptStates()
1091 { 1284 {
1285 return GetScriptStates(false);
1286 }
1287
1288 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1289 {
1092 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1290 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1093 1291
1094 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1292 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1095 if (engines == null) // No engine at all 1293 if (engines == null) // No engine at all
1096 return ret; 1294 return ret;
1097 1295
1098 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1296 Items.LockItemsForRead(true);
1099 1297 foreach (TaskInventoryItem item in m_items.Values)
1100 foreach (TaskInventoryItem item in scripts)
1101 { 1298 {
1102 foreach (IScriptModule e in engines) 1299 if (item.InvType == (int)InventoryType.LSL)
1103 { 1300 {
1104 if (e != null) 1301 foreach (IScriptModule e in engines)
1105 { 1302 {
1106 string n = e.GetXMLState(item.ItemID); 1303 if (e != null)
1107 if (n != String.Empty)
1108 { 1304 {
1109 if (!ret.ContainsKey(item.ItemID)) 1305 string n = e.GetXMLState(item.ItemID);
1110 ret[item.ItemID] = n; 1306 if (n != String.Empty)
1111 break; 1307 {
1308 if (oldIDs)
1309 {
1310 if (!ret.ContainsKey(item.OldItemID))
1311 ret[item.OldItemID] = n;
1312 }
1313 else
1314 {
1315 if (!ret.ContainsKey(item.ItemID))
1316 ret[item.ItemID] = n;
1317 }
1318 break;
1319 }
1112 } 1320 }
1113 } 1321 }
1114 } 1322 }
1115 } 1323 }
1116 1324 Items.LockItemsForRead(false);
1117 return ret; 1325 return ret;
1118 } 1326 }
1119 1327
@@ -1123,21 +1331,27 @@ namespace OpenSim.Region.Framework.Scenes
1123 if (engines == null) 1331 if (engines == null)
1124 return; 1332 return;
1125 1333
1126 List<TaskInventoryItem> scripts = GetInventoryScripts();
1127 1334
1128 foreach (TaskInventoryItem item in scripts) 1335 Items.LockItemsForRead(true);
1336
1337 foreach (TaskInventoryItem item in m_items.Values)
1129 { 1338 {
1130 foreach (IScriptModule engine in engines) 1339 if (item.InvType == (int)InventoryType.LSL)
1131 { 1340 {
1132 if (engine != null) 1341 foreach (IScriptModule engine in engines)
1133 { 1342 {
1134 if (item.OwnerChanged) 1343 if (engine != null)
1135 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1344 {
1136 item.OwnerChanged = false; 1345 if (item.OwnerChanged)
1137 engine.ResumeScript(item.ItemID); 1346 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1347 item.OwnerChanged = false;
1348 engine.ResumeScript(item.ItemID);
1349 }
1138 } 1350 }
1139 } 1351 }
1140 } 1352 }
1353
1354 Items.LockItemsForRead(false);
1141 } 1355 }
1142 } 1356 }
1143} 1357}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cd70de8..b54d1b8 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
31using System.Timers; 32using System.Timers;
@@ -72,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes
72// { 73// {
73// m_log.Debug("[ScenePresence] Destructor called"); 74// m_log.Debug("[ScenePresence] Destructor called");
74// } 75// }
75 76
76 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
77 78
78// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes(); 79// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
@@ -87,7 +88,9 @@ namespace OpenSim.Region.Framework.Scenes
87 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 88 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
88 /// issue #1716 89 /// issue #1716
89 /// </summary> 90 /// </summary>
90 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 91// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
92 // Value revised by KF 091121 by comparison with SL.
93 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
91 94
92 public UUID currentParcelUUID = UUID.Zero; 95 public UUID currentParcelUUID = UUID.Zero;
93 96
@@ -110,6 +113,7 @@ namespace OpenSim.Region.Framework.Scenes
110 { 113 {
111 get { return m_attachments; } 114 get { return m_attachments; }
112 } 115 }
116
113 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>(); 117 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
114 118
115 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>(); 119 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
@@ -121,8 +125,11 @@ namespace OpenSim.Region.Framework.Scenes
121 public Vector3 lastKnownAllowedPosition; 125 public Vector3 lastKnownAllowedPosition;
122 public bool sentMessageAboutRestrictedParcelFlyingDown; 126 public bool sentMessageAboutRestrictedParcelFlyingDown;
123 public Vector4 CollisionPlane = Vector4.UnitW; 127 public Vector4 CollisionPlane = Vector4.UnitW;
124 128
129 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
130 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
125 private Vector3 m_lastPosition; 131 private Vector3 m_lastPosition;
132 private Vector3 m_lastWorldPosition;
126 private Quaternion m_lastRotation; 133 private Quaternion m_lastRotation;
127 private Vector3 m_lastVelocity; 134 private Vector3 m_lastVelocity;
128 //private int m_lastTerseSent; 135 //private int m_lastTerseSent;
@@ -130,6 +137,11 @@ namespace OpenSim.Region.Framework.Scenes
130 private bool m_updateflag; 137 private bool m_updateflag;
131 private byte m_movementflag; 138 private byte m_movementflag;
132 private Vector3? m_forceToApply; 139 private Vector3? m_forceToApply;
140 private int m_userFlags;
141 public int UserFlags
142 {
143 get { return m_userFlags; }
144 }
133 private TeleportFlags m_teleportFlags; 145 private TeleportFlags m_teleportFlags;
134 public TeleportFlags TeleportFlags 146 public TeleportFlags TeleportFlags
135 { 147 {
@@ -160,9 +172,10 @@ namespace OpenSim.Region.Framework.Scenes
160 private int m_perfMonMS; 172 private int m_perfMonMS;
161 173
162 private bool m_setAlwaysRun; 174 private bool m_setAlwaysRun;
163
164 private bool m_forceFly; 175 private bool m_forceFly;
165 private bool m_flyDisabled; 176 private bool m_flyDisabled;
177 private bool m_flyingOld; // add for fly velocity control
178 public bool m_wasFlying; // add for fly velocity control
166 179
167 private float m_speedModifier = 1.0f; 180 private float m_speedModifier = 1.0f;
168 181
@@ -181,7 +194,8 @@ namespace OpenSim.Region.Framework.Scenes
181 protected RegionInfo m_regionInfo; 194 protected RegionInfo m_regionInfo;
182 protected ulong crossingFromRegion; 195 protected ulong crossingFromRegion;
183 196
184 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 197 private readonly Vector3[] Dir_Vectors = new Vector3[11];
198 private bool m_isNudging = false;
185 199
186 // Position of agent's camera in world (region cordinates) 200 // Position of agent's camera in world (region cordinates)
187 protected Vector3 m_CameraCenter; 201 protected Vector3 m_CameraCenter;
@@ -206,17 +220,25 @@ namespace OpenSim.Region.Framework.Scenes
206 private bool m_autopilotMoving; 220 private bool m_autopilotMoving;
207 private Vector3 m_autoPilotTarget; 221 private Vector3 m_autoPilotTarget;
208 private bool m_sitAtAutoTarget; 222 private bool m_sitAtAutoTarget;
223 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
209 224
210 private string m_nextSitAnimation = String.Empty; 225 private string m_nextSitAnimation = String.Empty;
211 226
212 //PauPaw:Proper PID Controler for autopilot************ 227 //PauPaw:Proper PID Controler for autopilot************
213 private bool m_moveToPositionInProgress; 228 private bool m_moveToPositionInProgress;
214 private Vector3 m_moveToPositionTarget; 229 private Vector3 m_moveToPositionTarget;
230 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
215 231
216 private bool m_followCamAuto; 232 private bool m_followCamAuto;
217 233
218 private int m_movementUpdateCount; 234 private int m_movementUpdateCount;
235 private int m_lastColCount = -1; //KF: Look for Collision chnages
236 private int m_updateCount = 0; //KF: Update Anims for a while
237 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
219 private const int NumMovementsBetweenRayCast = 5; 238 private const int NumMovementsBetweenRayCast = 5;
239 private List<uint> m_lastColliders = new List<uint>();
240
241 private object m_syncRoot = new Object();
220 242
221 private bool CameraConstraintActive; 243 private bool CameraConstraintActive;
222 //private int m_moveToPositionStateStatus; 244 //private int m_moveToPositionStateStatus;
@@ -243,7 +265,9 @@ namespace OpenSim.Region.Framework.Scenes
243 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 265 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
244 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 266 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
245 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 267 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
246 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 268 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
269 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
270 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
247 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 271 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
248 } 272 }
249 273
@@ -450,7 +474,8 @@ namespace OpenSim.Region.Framework.Scenes
450 get 474 get
451 { 475 {
452 PhysicsActor actor = m_physicsActor; 476 PhysicsActor actor = m_physicsActor;
453 if (actor != null) 477// if (actor != null)
478 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
454 m_pos = actor.Position; 479 m_pos = actor.Position;
455 else 480 else
456 { 481 {
@@ -472,7 +497,7 @@ namespace OpenSim.Region.Framework.Scenes
472 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 497 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
473 if (part != null) 498 if (part != null)
474 { 499 {
475 return m_parentPosition + (m_pos * part.GetWorldRotation()); 500 return part.AbsolutePosition + (m_pos * part.GetWorldRotation());
476 } 501 }
477 else 502 else
478 { 503 {
@@ -499,7 +524,8 @@ namespace OpenSim.Region.Framework.Scenes
499 } 524 }
500 } 525 }
501 526
502 m_pos = value; 527 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
528 m_pos = value;
503 m_parentPosition = Vector3.Zero; 529 m_parentPosition = Vector3.Zero;
504 } 530 }
505 } 531 }
@@ -543,10 +569,39 @@ namespace OpenSim.Region.Framework.Scenes
543 } 569 }
544 } 570 }
545 571
572 public Quaternion OffsetRotation
573 {
574 get { return m_offsetRotation; }
575 set { m_offsetRotation = value; }
576 }
577
546 public Quaternion Rotation 578 public Quaternion Rotation
547 { 579 {
548 get { return m_bodyRot; } 580 get {
549 set { m_bodyRot = value; } 581 if (m_parentID != 0)
582 {
583 if (m_offsetRotation != null)
584 {
585 return m_offsetRotation;
586 }
587 else
588 {
589 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
590 }
591
592 }
593 else
594 {
595 return m_bodyRot;
596 }
597 }
598 set {
599 m_bodyRot = value;
600 if (m_parentID != 0)
601 {
602 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
603 }
604 }
550 } 605 }
551 606
552 public Quaternion PreviousRotation 607 public Quaternion PreviousRotation
@@ -571,11 +626,21 @@ namespace OpenSim.Region.Framework.Scenes
571 626
572 private uint m_parentID; 627 private uint m_parentID;
573 628
629
630 private UUID m_linkedPrim;
631
574 public uint ParentID 632 public uint ParentID
575 { 633 {
576 get { return m_parentID; } 634 get { return m_parentID; }
577 set { m_parentID = value; } 635 set { m_parentID = value; }
578 } 636 }
637
638 public UUID LinkedPrim
639 {
640 get { return m_linkedPrim; }
641 set { m_linkedPrim = value; }
642 }
643
579 public float Health 644 public float Health
580 { 645 {
581 get { return m_health; } 646 get { return m_health; }
@@ -697,7 +762,7 @@ namespace OpenSim.Region.Framework.Scenes
697 CreateSceneViewer(); 762 CreateSceneViewer();
698 m_animator = new ScenePresenceAnimator(this); 763 m_animator = new ScenePresenceAnimator(this);
699 } 764 }
700 765
701 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 766 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
702 { 767 {
703 m_rootRegionHandle = reginfo.RegionHandle; 768 m_rootRegionHandle = reginfo.RegionHandle;
@@ -711,6 +776,7 @@ namespace OpenSim.Region.Framework.Scenes
711 m_localId = m_scene.AllocateLocalId(); 776 m_localId = m_scene.AllocateLocalId();
712 777
713 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 778 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
779 m_userFlags = account.UserFlags;
714 780
715 if (account != null) 781 if (account != null)
716 m_userLevel = account.UserLevel; 782 m_userLevel = account.UserLevel;
@@ -729,10 +795,7 @@ namespace OpenSim.Region.Framework.Scenes
729 m_reprioritization_timer.AutoReset = false; 795 m_reprioritization_timer.AutoReset = false;
730 796
731 AdjustKnownSeeds(); 797 AdjustKnownSeeds();
732
733 // TODO: I think, this won't send anything, as we are still a child here...
734 Animator.TrySetMovementAnimation("STAND"); 798 Animator.TrySetMovementAnimation("STAND");
735
736 // we created a new ScenePresence (a new child agent) in a fresh region. 799 // we created a new ScenePresence (a new child agent) in a fresh region.
737 // Request info about all the (root) agents in this region 800 // Request info about all the (root) agents in this region
738 // Note: This won't send data *to* other clients in that region (children don't send) 801 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -783,25 +846,47 @@ namespace OpenSim.Region.Framework.Scenes
783 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 846 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
784 Dir_Vectors[4] = Vector3.UnitZ; //UP 847 Dir_Vectors[4] = Vector3.UnitZ; //UP
785 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 848 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
786 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 849 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
787 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 850 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
788 Dir_Vectors[7] = -Vector3.UnitX; //BACK 851 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
852 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
853 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
789 } 854 }
790 855
791 private Vector3[] GetWalkDirectionVectors() 856 private Vector3[] GetWalkDirectionVectors()
792 { 857 {
793 Vector3[] vector = new Vector3[9]; 858 Vector3[] vector = new Vector3[11];
794 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 859 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
795 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 860 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
796 vector[2] = Vector3.UnitY; //LEFT 861 vector[2] = Vector3.UnitY; //LEFT
797 vector[3] = -Vector3.UnitY; //RIGHT 862 vector[3] = -Vector3.UnitY; //RIGHT
798 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 863 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
799 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 864 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
800 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 865 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
801 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 866 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
802 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 867 vector[8] = Vector3.UnitY; //LEFT_NUDGE
868 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
869 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
803 return vector; 870 return vector;
804 } 871 }
872
873 private bool[] GetDirectionIsNudge()
874 {
875 bool[] isNudge = new bool[11];
876 isNudge[0] = false; //FORWARD
877 isNudge[1] = false; //BACK
878 isNudge[2] = false; //LEFT
879 isNudge[3] = false; //RIGHT
880 isNudge[4] = false; //UP
881 isNudge[5] = false; //DOWN
882 isNudge[6] = true; //FORWARD_NUDGE
883 isNudge[7] = true; //BACK_NUDGE
884 isNudge[8] = true; //LEFT_NUDGE
885 isNudge[9] = true; //RIGHT_NUDGE
886 isNudge[10] = true; //DOWN_Nudge
887 return isNudge;
888 }
889
805 890
806 #endregion 891 #endregion
807 892
@@ -863,6 +948,62 @@ namespace OpenSim.Region.Framework.Scenes
863 pos.Y = crossedBorder.BorderLine.Z - 1; 948 pos.Y = crossedBorder.BorderLine.Z - 1;
864 } 949 }
865 950
951 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
952 if (land != null)
953 {
954 // If we come in via login, landmark or map, we want to
955 // honor landing points. If we come in via Lure, we want
956 // to ignore them.
957 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
958 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ||
959 (m_teleportFlags & TeleportFlags.ViaLocation) != 0)
960 {
961 // Don't restrict gods, estate managers, or land owners to
962 // the TP point. This behaviour mimics agni.
963 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
964 land.LandData.UserLocation != Vector3.Zero &&
965 GodLevel < 200 &&
966 ((land.LandData.OwnerID != m_uuid &&
967 (!m_scene.Permissions.IsGod(m_uuid)) &&
968 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0))
969 {
970 pos = land.LandData.UserLocation;
971 }
972 }
973
974 land.SendLandUpdateToClient(ControllingClient);
975 }
976
977 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
978 {
979 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
980
981 if (pos.X < 0)
982 {
983 emergencyPos.X = (int)Constants.RegionSize + pos.X;
984 if (!(pos.Y < 0))
985 emergencyPos.Y = pos.Y;
986 if (!(pos.Z < 0))
987 emergencyPos.Z = pos.Z;
988 }
989 if (pos.Y < 0)
990 {
991 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
992 if (!(pos.X < 0))
993 emergencyPos.X = pos.X;
994 if (!(pos.Z < 0))
995 emergencyPos.Z = pos.Z;
996 }
997 if (pos.Z < 0)
998 {
999 emergencyPos.Z = 128;
1000 if (!(pos.Y < 0))
1001 emergencyPos.Y = pos.Y;
1002 if (!(pos.X < 0))
1003 emergencyPos.X = pos.X;
1004 }
1005 }
1006
866 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1007 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
867 { 1008 {
868 m_log.WarnFormat( 1009 m_log.WarnFormat(
@@ -987,16 +1128,21 @@ namespace OpenSim.Region.Framework.Scenes
987 /// <summary> 1128 /// <summary>
988 /// Removes physics plugin scene representation of this agent if it exists. 1129 /// Removes physics plugin scene representation of this agent if it exists.
989 /// </summary> 1130 /// </summary>
990 private void RemoveFromPhysicalScene() 1131 public void RemoveFromPhysicalScene()
991 { 1132 {
992 if (PhysicsActor != null) 1133 if (PhysicsActor != null)
993 { 1134 {
994 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1135 try
995 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1136 {
996 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1137 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
997 m_physicsActor.UnSubscribeEvents(); 1138 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
998 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1139 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
999 PhysicsActor = null; 1140 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1141 m_physicsActor.UnSubscribeEvents();
1142 PhysicsActor = null;
1143 }
1144 catch
1145 { }
1000 } 1146 }
1001 } 1147 }
1002 1148
@@ -1007,11 +1153,13 @@ namespace OpenSim.Region.Framework.Scenes
1007 public void Teleport(Vector3 pos) 1153 public void Teleport(Vector3 pos)
1008 { 1154 {
1009 bool isFlying = false; 1155 bool isFlying = false;
1156
1010 if (m_physicsActor != null) 1157 if (m_physicsActor != null)
1011 isFlying = m_physicsActor.Flying; 1158 isFlying = m_physicsActor.Flying;
1012 1159
1013 RemoveFromPhysicalScene(); 1160 RemoveFromPhysicalScene();
1014 Velocity = Vector3.Zero; 1161 Velocity = Vector3.Zero;
1162 CheckLandingPoint(ref pos);
1015 AbsolutePosition = pos; 1163 AbsolutePosition = pos;
1016 AddToPhysicalScene(isFlying); 1164 AddToPhysicalScene(isFlying);
1017 if (m_appearance != null) 1165 if (m_appearance != null)
@@ -1021,6 +1169,7 @@ namespace OpenSim.Region.Framework.Scenes
1021 } 1169 }
1022 1170
1023 SendTerseUpdateToAllClients(); 1171 SendTerseUpdateToAllClients();
1172
1024 } 1173 }
1025 1174
1026 public void TeleportWithMomentum(Vector3 pos) 1175 public void TeleportWithMomentum(Vector3 pos)
@@ -1030,6 +1179,7 @@ namespace OpenSim.Region.Framework.Scenes
1030 isFlying = m_physicsActor.Flying; 1179 isFlying = m_physicsActor.Flying;
1031 1180
1032 RemoveFromPhysicalScene(); 1181 RemoveFromPhysicalScene();
1182 CheckLandingPoint(ref pos);
1033 AbsolutePosition = pos; 1183 AbsolutePosition = pos;
1034 AddToPhysicalScene(isFlying); 1184 AddToPhysicalScene(isFlying);
1035 if (m_appearance != null) 1185 if (m_appearance != null)
@@ -1239,6 +1389,7 @@ namespace OpenSim.Region.Framework.Scenes
1239 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1389 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1240 1390
1241 m_pos = m_LastFinitePos; 1391 m_pos = m_LastFinitePos;
1392
1242 if (!m_pos.IsFinite()) 1393 if (!m_pos.IsFinite())
1243 { 1394 {
1244 m_pos.X = 127f; 1395 m_pos.X = 127f;
@@ -1305,7 +1456,6 @@ namespace OpenSim.Region.Framework.Scenes
1305 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1456 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1306 } 1457 }
1307 } 1458 }
1308
1309 lock (scriptedcontrols) 1459 lock (scriptedcontrols)
1310 { 1460 {
1311 if (scriptedcontrols.Count > 0) 1461 if (scriptedcontrols.Count > 0)
@@ -1320,6 +1470,9 @@ namespace OpenSim.Region.Framework.Scenes
1320 1470
1321 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1471 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1322 { 1472 {
1473 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1474 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1475
1323 // TODO: This doesn't prevent the user from walking yet. 1476 // TODO: This doesn't prevent the user from walking yet.
1324 // Setting parent ID would fix this, if we knew what value 1477 // Setting parent ID would fix this, if we knew what value
1325 // to use. Or we could add a m_isSitting variable. 1478 // to use. Or we could add a m_isSitting variable.
@@ -1368,12 +1521,20 @@ namespace OpenSim.Region.Framework.Scenes
1368 if (actor.Flying != oldflying) 1521 if (actor.Flying != oldflying)
1369 update_movementflag = true; 1522 update_movementflag = true;
1370 1523
1524 if (m_animator.m_jumping) // add for jumping
1525 update_movementflag = true;
1526
1371 if (q != m_bodyRot) 1527 if (q != m_bodyRot)
1372 { 1528 {
1373 m_bodyRot = q; 1529 m_bodyRot = q;
1374 update_rotation = true; 1530 update_rotation = true;
1375 } 1531 }
1376 1532
1533 //guilty until proven innocent..
1534 bool Nudging = true;
1535 //Basically, if there is at least one non-nudge control then we don't need
1536 //to worry about stopping the avatar
1537
1377 if (m_parentID == 0) 1538 if (m_parentID == 0)
1378 { 1539 {
1379 bool bAllowUpdateMoveToPosition = false; 1540 bool bAllowUpdateMoveToPosition = false;
@@ -1388,9 +1549,12 @@ namespace OpenSim.Region.Framework.Scenes
1388 else 1549 else
1389 dirVectors = Dir_Vectors; 1550 dirVectors = Dir_Vectors;
1390 1551
1391 // The fact that m_movementflag is a byte needs to be fixed 1552 bool[] isNudge = GetDirectionIsNudge();
1392 // it really should be a uint 1553
1393 uint nudgehack = 250; 1554
1555
1556
1557
1394 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1558 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1395 { 1559 {
1396 if (((uint)flags & (uint)DCF) != 0) 1560 if (((uint)flags & (uint)DCF) != 0)
@@ -1400,40 +1564,28 @@ namespace OpenSim.Region.Framework.Scenes
1400 try 1564 try
1401 { 1565 {
1402 agent_control_v3 += dirVectors[i]; 1566 agent_control_v3 += dirVectors[i];
1403 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1567 if (isNudge[i] == false)
1568 {
1569 Nudging = false;
1570 }
1404 } 1571 }
1405 catch (IndexOutOfRangeException) 1572 catch (IndexOutOfRangeException)
1406 { 1573 {
1407 // Why did I get this? 1574 // Why did I get this?
1408 } 1575 }
1409 1576
1410 if ((m_movementflag & (byte)(uint)DCF) == 0) 1577 if ((m_movementflag & (uint)DCF) == 0)
1411 { 1578 {
1412 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1413 {
1414 m_movementflag |= (byte)nudgehack;
1415 }
1416 m_movementflag += (byte)(uint)DCF; 1579 m_movementflag += (byte)(uint)DCF;
1417 update_movementflag = true; 1580 update_movementflag = true;
1418 } 1581 }
1419 } 1582 }
1420 else 1583 else
1421 { 1584 {
1422 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1585 if ((m_movementflag & (uint)DCF) != 0)
1423 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1424 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1425 ) // This or is for Nudge forward
1426 { 1586 {
1427 m_movementflag -= ((byte)(uint)DCF); 1587 m_movementflag -= (byte)(uint)DCF;
1428
1429 update_movementflag = true; 1588 update_movementflag = true;
1430 /*
1431 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1432 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1433 {
1434 m_log.Debug("Removed Hack flag");
1435 }
1436 */
1437 } 1589 }
1438 else 1590 else
1439 { 1591 {
@@ -1442,7 +1594,6 @@ namespace OpenSim.Region.Framework.Scenes
1442 } 1594 }
1443 i++; 1595 i++;
1444 } 1596 }
1445
1446 //Paupaw:Do Proper PID for Autopilot here 1597 //Paupaw:Do Proper PID for Autopilot here
1447 if (bResetMoveToPosition) 1598 if (bResetMoveToPosition)
1448 { 1599 {
@@ -1477,6 +1628,9 @@ namespace OpenSim.Region.Framework.Scenes
1477 // Ignore z component of vector 1628 // Ignore z component of vector
1478 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1629 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1479 LocalVectorToTarget2D.Normalize(); 1630 LocalVectorToTarget2D.Normalize();
1631
1632 //We're not nudging
1633 Nudging = false;
1480 agent_control_v3 += LocalVectorToTarget2D; 1634 agent_control_v3 += LocalVectorToTarget2D;
1481 1635
1482 // update avatar movement flags. the avatar coordinate system is as follows: 1636 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1567,13 +1721,13 @@ namespace OpenSim.Region.Framework.Scenes
1567 // m_log.DebugFormat( 1721 // m_log.DebugFormat(
1568 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1722 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1569 1723
1570 AddNewMovement(agent_control_v3, q); 1724 AddNewMovement(agent_control_v3, q, Nudging);
1571 1725
1572 1726
1573 } 1727 }
1574 } 1728 }
1575 1729
1576 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1730 if (update_movementflag && !SitGround)
1577 Animator.UpdateMovementAnimations(); 1731 Animator.UpdateMovementAnimations();
1578 1732
1579 m_scene.EventManager.TriggerOnClientMovement(this); 1733 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1588,7 +1742,6 @@ namespace OpenSim.Region.Framework.Scenes
1588 m_sitAtAutoTarget = false; 1742 m_sitAtAutoTarget = false;
1589 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1743 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1590 //proxy.PCode = (byte)PCode.ParticleSystem; 1744 //proxy.PCode = (byte)PCode.ParticleSystem;
1591
1592 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1745 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1593 proxyObjectGroup.AttachToScene(m_scene); 1746 proxyObjectGroup.AttachToScene(m_scene);
1594 1747
@@ -1629,8 +1782,8 @@ namespace OpenSim.Region.Framework.Scenes
1629 return; 1782 return;
1630 } 1783 }
1631 m_moveToPositionInProgress = true; 1784 m_moveToPositionInProgress = true;
1632 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1785 m_moveToPositionTarget = new Vector3(locx, locy, locz + (m_appearance.AvatarHeight / 2.0f));
1633 } 1786 }
1634 catch (Exception ex) 1787 catch (Exception ex)
1635 { 1788 {
1636 //Why did I get this error? 1789 //Why did I get this error?
@@ -1652,7 +1805,7 @@ namespace OpenSim.Region.Framework.Scenes
1652 Velocity = Vector3.Zero; 1805 Velocity = Vector3.Zero;
1653 SendAvatarDataToAllAgents(); 1806 SendAvatarDataToAllAgents();
1654 1807
1655 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1808 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1656 } 1809 }
1657 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1810 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1658 m_requestedSitTargetUUID = UUID.Zero; 1811 m_requestedSitTargetUUID = UUID.Zero;
@@ -1689,25 +1842,22 @@ namespace OpenSim.Region.Framework.Scenes
1689 1842
1690 if (m_parentID != 0) 1843 if (m_parentID != 0)
1691 { 1844 {
1692 m_log.Debug("StandupCode Executed"); 1845 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1693 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1694 if (part != null) 1846 if (part != null)
1695 { 1847 {
1848 part.TaskInventory.LockItemsForRead(true);
1696 TaskInventoryDictionary taskIDict = part.TaskInventory; 1849 TaskInventoryDictionary taskIDict = part.TaskInventory;
1697 if (taskIDict != null) 1850 if (taskIDict != null)
1698 { 1851 {
1699 lock (taskIDict) 1852 foreach (UUID taskID in taskIDict.Keys)
1700 { 1853 {
1701 foreach (UUID taskID in taskIDict.Keys) 1854 UnRegisterControlEventsToScript(LocalId, taskID);
1702 { 1855 taskIDict[taskID].PermsMask &= ~(
1703 UnRegisterControlEventsToScript(LocalId, taskID); 1856 2048 | //PERMISSION_CONTROL_CAMERA
1704 taskIDict[taskID].PermsMask &= ~( 1857 4); // PERMISSION_TAKE_CONTROLS
1705 2048 | //PERMISSION_CONTROL_CAMERA
1706 4); // PERMISSION_TAKE_CONTROLS
1707 }
1708 } 1858 }
1709
1710 } 1859 }
1860 part.TaskInventory.LockItemsForRead(false);
1711 // Reset sit target. 1861 // Reset sit target.
1712 if (part.GetAvatarOnSitTarget() == UUID) 1862 if (part.GetAvatarOnSitTarget() == UUID)
1713 part.SitTargetAvatar = UUID.Zero; 1863 part.SitTargetAvatar = UUID.Zero;
@@ -1716,16 +1866,55 @@ namespace OpenSim.Region.Framework.Scenes
1716 m_parentPosition = part.GetWorldPosition(); 1866 m_parentPosition = part.GetWorldPosition();
1717 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1867 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1718 } 1868 }
1869 // part.GetWorldRotation() is the rotation of the object being sat on
1870 // Rotation is the sittiing Av's rotation
1871
1872 Quaternion partRot;
1873// if (part.LinkNum == 1)
1874// { // Root prim of linkset
1875// partRot = part.ParentGroup.RootPart.RotationOffset;
1876// }
1877// else
1878// { // single or child prim
1879
1880// }
1881 if (part == null) //CW: Part may be gone. llDie() for example.
1882 {
1883 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1884 }
1885 else
1886 {
1887 partRot = part.GetWorldRotation();
1888 }
1889
1890 Quaternion partIRot = Quaternion.Inverse(partRot);
1719 1891
1892 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1893 Vector3 avStandUp = new Vector3(0.3f, 0f, 0f) * avatarRot; // 0.3M infront of av
1894
1895
1720 if (m_physicsActor == null) 1896 if (m_physicsActor == null)
1721 { 1897 {
1722 AddToPhysicalScene(false); 1898 AddToPhysicalScene(false);
1723 } 1899 }
1724 1900 //CW: If the part isn't null then we can set the current position
1725 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1901 if (part != null)
1726 m_parentPosition = Vector3.Zero; 1902 {
1727 1903 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1728 m_parentID = 0; 1904 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1905 part.IsOccupied = false;
1906 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1907 }
1908 else
1909 {
1910 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1911 AbsolutePosition = m_lastWorldPosition;
1912 }
1913
1914 m_parentPosition = Vector3.Zero;
1915 m_parentID = 0;
1916 m_linkedPrim = UUID.Zero;
1917 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1729 SendAvatarDataToAllAgents(); 1918 SendAvatarDataToAllAgents();
1730 m_requestedSitTargetID = 0; 1919 m_requestedSitTargetID = 0;
1731 if (m_physicsActor != null && m_appearance != null) 1920 if (m_physicsActor != null && m_appearance != null)
@@ -1734,7 +1923,6 @@ namespace OpenSim.Region.Framework.Scenes
1734 SetHeight(m_appearance.AvatarHeight); 1923 SetHeight(m_appearance.AvatarHeight);
1735 } 1924 }
1736 } 1925 }
1737
1738 Animator.TrySetMovementAnimation("STAND"); 1926 Animator.TrySetMovementAnimation("STAND");
1739 } 1927 }
1740 1928
@@ -1765,13 +1953,9 @@ namespace OpenSim.Region.Framework.Scenes
1765 Vector3 avSitOffSet = part.SitTargetPosition; 1953 Vector3 avSitOffSet = part.SitTargetPosition;
1766 Quaternion avSitOrientation = part.SitTargetOrientation; 1954 Quaternion avSitOrientation = part.SitTargetOrientation;
1767 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1955 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1768 1956 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1769 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1957 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1770 bool SitTargetisSet = 1958 if (SitTargetisSet && !SitTargetOccupied)
1771 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1772 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1773
1774 if (SitTargetisSet && SitTargetUnOccupied)
1775 { 1959 {
1776 //switch the target to this prim 1960 //switch the target to this prim
1777 return part; 1961 return part;
@@ -1785,85 +1969,168 @@ namespace OpenSim.Region.Framework.Scenes
1785 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 1969 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1786 { 1970 {
1787 bool autopilot = true; 1971 bool autopilot = true;
1972 Vector3 autopilotTarget = new Vector3();
1973 Quaternion sitOrientation = Quaternion.Identity;
1788 Vector3 pos = new Vector3(); 1974 Vector3 pos = new Vector3();
1789 Quaternion sitOrientation = pSitOrientation;
1790 Vector3 cameraEyeOffset = Vector3.Zero; 1975 Vector3 cameraEyeOffset = Vector3.Zero;
1791 Vector3 cameraAtOffset = Vector3.Zero; 1976 Vector3 cameraAtOffset = Vector3.Zero;
1792 bool forceMouselook = false; 1977 bool forceMouselook = false;
1793 1978
1794 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 1979 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1795 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 1980 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1796 if (part != null) 1981 if (part == null) return;
1797 { 1982
1798 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 1983 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1799 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 1984 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1800 1985
1801 // Is a sit target available? 1986 // part is the prim to sit on
1802 Vector3 avSitOffSet = part.SitTargetPosition; 1987 // offset is the world-ref vector distance from that prim center to the click-spot
1803 Quaternion avSitOrientation = part.SitTargetOrientation; 1988 // UUID is the UUID of the Avatar doing the clicking
1804 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 1989
1805 1990 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1806 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 1991
1807 bool SitTargetisSet = 1992 // Is a sit target available?
1808 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 1993 Vector3 avSitOffSet = part.SitTargetPosition;
1809 ( 1994 Quaternion avSitOrientation = part.SitTargetOrientation;
1810 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 1995
1811 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 1996 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1812 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 1997 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1813 ) 1998 Quaternion partRot;
1814 )); 1999// if (part.LinkNum == 1)
1815 2000// { // Root prim of linkset
1816 if (SitTargetisSet && SitTargetUnOccupied) 2001// partRot = part.ParentGroup.RootPart.RotationOffset;
1817 { 2002// }
1818 part.SitTargetAvatar = UUID; 2003// else
1819 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 2004// { // single or child prim
1820 sitOrientation = avSitOrientation; 2005 partRot = part.GetWorldRotation();
1821 autopilot = false; 2006// }
1822 } 2007 Quaternion partIRot = Quaternion.Inverse(partRot);
1823 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2008//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1824 2009 // Sit analysis rewritten by KF 091125
1825 pos = part.AbsolutePosition + offset; 2010 if (SitTargetisSet) // scipted sit
1826 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 2011 {
1827 //{ 2012 if (!part.IsOccupied)
1828 // offset = pos; 2013 {
1829 //autopilot = false; 2014//Console.WriteLine("Scripted, unoccupied");
1830 //} 2015 part.SitTargetAvatar = UUID; // set that Av will be on it
1831 if (m_physicsActor != null) 2016 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1832 { 2017
1833 // If we're not using the client autopilot, we're immediately warping the avatar to the location 2018 Quaternion nrot = avSitOrientation;
1834 // We can remove the physicsActor until they stand up. 2019 if (!part.IsRoot)
1835 m_sitAvatarHeight = m_physicsActor.Size.Z;
1836
1837 if (autopilot)
1838 { 2020 {
1839 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 2021 nrot = part.RotationOffset * avSitOrientation;
1840 {
1841 autopilot = false;
1842
1843 RemoveFromPhysicalScene();
1844 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1845 }
1846 } 2022 }
1847 else 2023 sitOrientation = nrot; // Change rotatione to the scripted one
2024 OffsetRotation = nrot;
2025 autopilot = false; // Jump direct to scripted llSitPos()
2026 }
2027 else
2028 {
2029//Console.WriteLine("Scripted, occupied");
2030 return;
2031 }
2032 }
2033 else // Not Scripted
2034 {
2035 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
2036 {
2037 // large prim & offset, ignore if other Avs sitting
2038// offset.Z -= 0.05f;
2039 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
2040 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
2041
2042//Console.WriteLine(" offset ={0}", offset);
2043//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
2044//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
2045
2046 }
2047 else // small offset
2048 {
2049//Console.WriteLine("Small offset");
2050 if (!part.IsOccupied)
2051 {
2052 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2053 autopilotTarget = part.AbsolutePosition;
2054//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2055 }
2056 else return; // occupied small
2057 } // end large/small
2058 } // end Scripted/not
2059
2060 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2061
2062 cameraAtOffset = part.GetCameraAtOffset();
2063 cameraEyeOffset = part.GetCameraEyeOffset();
2064 forceMouselook = part.GetForceMouselook();
2065 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2066 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2067
2068 if (m_physicsActor != null)
2069 {
2070 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2071 // We can remove the physicsActor until they stand up.
2072 m_sitAvatarHeight = m_physicsActor.Size.Z;
2073 if (autopilot)
2074 { // its not a scripted sit
2075// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2076 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1848 { 2077 {
2078 autopilot = false; // close enough
2079 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2080 Not using the part's position because returning the AV to the last known standing
2081 position is likely to be more friendly, isn't it? */
1849 RemoveFromPhysicalScene(); 2082 RemoveFromPhysicalScene();
1850 } 2083 Velocity = Vector3.Zero;
2084 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2085 } // else the autopilot will get us close
2086 }
2087 else
2088 { // its a scripted sit
2089 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2090 I *am* using the part's position this time because we have no real idea how far away
2091 the avatar is from the sit target. */
2092 RemoveFromPhysicalScene();
2093 Velocity = Vector3.Zero;
1851 } 2094 }
1852
1853 cameraAtOffset = part.GetCameraAtOffset();
1854 cameraEyeOffset = part.GetCameraEyeOffset();
1855 forceMouselook = part.GetForceMouselook();
1856 } 2095 }
1857 2096 else return; // physactor is null!
1858 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2097
1859 m_requestedSitTargetUUID = targetID; 2098 Vector3 offsetr; // = offset * partIRot;
2099 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2100 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2101 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2102 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2103 //offsetr = offset * partIRot;
2104//
2105 // }
2106 // else
2107 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2108 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2109 // (offset * partRot);
2110 // }
2111
2112//Console.WriteLine(" ");
2113//Console.WriteLine("link number ={0}", part.LinkNum);
2114//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2115//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2116//Console.WriteLine("Click offst ={0}", offset);
2117//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2118//Console.WriteLine("offsetr ={0}", offsetr);
2119//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2120//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2121
2122 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2123 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2124
2125 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1860 // This calls HandleAgentSit twice, once from here, and the client calls 2126 // This calls HandleAgentSit twice, once from here, and the client calls
1861 // HandleAgentSit itself after it gets to the location 2127 // HandleAgentSit itself after it gets to the location
1862 // It doesn't get to the location until we've moved them there though 2128 // It doesn't get to the location until we've moved them there though
1863 // which happens in HandleAgentSit :P 2129 // which happens in HandleAgentSit :P
1864 m_autopilotMoving = autopilot; 2130 m_autopilotMoving = autopilot;
1865 m_autoPilotTarget = pos; 2131 m_autoPilotTarget = autopilotTarget;
1866 m_sitAtAutoTarget = autopilot; 2132 m_sitAtAutoTarget = autopilot;
2133 m_initialSitTarget = autopilotTarget;
1867 if (!autopilot) 2134 if (!autopilot)
1868 HandleAgentSit(remoteClient, UUID); 2135 HandleAgentSit(remoteClient, UUID);
1869 } 2136 }
@@ -2158,47 +2425,130 @@ namespace OpenSim.Region.Framework.Scenes
2158 { 2425 {
2159 if (part != null) 2426 if (part != null)
2160 { 2427 {
2428//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2161 if (part.GetAvatarOnSitTarget() == UUID) 2429 if (part.GetAvatarOnSitTarget() == UUID)
2162 { 2430 {
2431//Console.WriteLine("Scripted Sit");
2432 // Scripted sit
2163 Vector3 sitTargetPos = part.SitTargetPosition; 2433 Vector3 sitTargetPos = part.SitTargetPosition;
2164 Quaternion sitTargetOrient = part.SitTargetOrientation; 2434 Quaternion sitTargetOrient = part.SitTargetOrientation;
2165
2166 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2167 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2168
2169 //Quaternion result = (sitTargetOrient * vq) * nq;
2170
2171 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2435 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2172 m_pos += SIT_TARGET_ADJUSTMENT; 2436 m_pos += SIT_TARGET_ADJUSTMENT;
2437 if (!part.IsRoot)
2438 {
2439 m_pos *= part.RotationOffset;
2440 }
2173 m_bodyRot = sitTargetOrient; 2441 m_bodyRot = sitTargetOrient;
2174 //Rotation = sitTargetOrient;
2175 m_parentPosition = part.AbsolutePosition; 2442 m_parentPosition = part.AbsolutePosition;
2176 2443 part.IsOccupied = true;
2177 //SendTerseUpdateToAllClients(); 2444 part.ParentGroup.AddAvatar(agentID);
2178 } 2445 }
2179 else 2446 else
2180 { 2447 {
2181 m_pos -= part.AbsolutePosition; 2448 // if m_avUnscriptedSitPos is zero then Av sits above center
2449 // Else Av sits at m_avUnscriptedSitPos
2450
2451 // Non-scripted sit by Kitto Flora 21Nov09
2452 // Calculate angle of line from prim to Av
2453 Quaternion partIRot;
2454// if (part.LinkNum == 1)
2455// { // Root prim of linkset
2456// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2457// }
2458// else
2459// { // single or child prim
2460 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2461// }
2462 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2463 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2464 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2465 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2466 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2467 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2468 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2469 // Av sits at world euler <0,0, z>, translated by part rotation
2470 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2471
2182 m_parentPosition = part.AbsolutePosition; 2472 m_parentPosition = part.AbsolutePosition;
2183 } 2473 part.IsOccupied = true;
2474 part.ParentGroup.AddAvatar(agentID);
2475 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2476 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2477 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2478 m_avUnscriptedSitPos; // adds click offset, if any
2479 //Set up raytrace to find top surface of prim
2480 Vector3 size = part.Scale;
2481 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2482 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2483 Vector3 down = new Vector3(0f, 0f, -1f);
2484//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2485 m_scene.PhysicsScene.RaycastWorld(
2486 start, // Vector3 position,
2487 down, // Vector3 direction,
2488 mag, // float length,
2489 SitAltitudeCallback); // retMethod
2490 } // end scripted/not
2184 } 2491 }
2185 else 2492 else // no Av
2186 { 2493 {
2187 return; 2494 return;
2188 } 2495 }
2189 } 2496 }
2190 m_parentID = m_requestedSitTargetID;
2191 2497
2498 //We want our offsets to reference the root prim, not the child we may have sat on
2499 if (!part.IsRoot)
2500 {
2501 m_parentID = part.ParentGroup.RootPart.LocalId;
2502 m_pos += part.OffsetPosition;
2503 }
2504 else
2505 {
2506 m_parentID = m_requestedSitTargetID;
2507 }
2508
2509 m_linkedPrim = part.UUID;
2510 if (part.GetAvatarOnSitTarget() != UUID)
2511 {
2512 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2513 }
2192 Velocity = Vector3.Zero; 2514 Velocity = Vector3.Zero;
2193 RemoveFromPhysicalScene(); 2515 RemoveFromPhysicalScene();
2194
2195 Animator.TrySetMovementAnimation(sitAnimation); 2516 Animator.TrySetMovementAnimation(sitAnimation);
2196 SendAvatarDataToAllAgents(); 2517 SendAvatarDataToAllAgents();
2197 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2198 // So we're also sending a terse update (which has avatar rotation)
2199 // [Update] We do now.
2200 //SendTerseUpdateToAllClients(); 2518 //SendTerseUpdateToAllClients();
2201 } 2519 }
2520
2521 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2522 {
2523 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2524 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2525 if(hitYN)
2526 {
2527 // m_pos = Av offset from prim center to make look like on center
2528 // m_parentPosition = Actual center pos of prim
2529 // collisionPoint = spot on prim where we want to sit
2530 // collisionPoint.Z = global sit surface height
2531 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2532 Quaternion partIRot;
2533// if (part.LinkNum == 1)
2534/// { // Root prim of linkset
2535// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2536// }
2537// else
2538// { // single or child prim
2539 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2540// }
2541 if (m_initialSitTarget != null)
2542 {
2543 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2544 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2545 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2546 m_pos += offset;
2547 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2548 }
2549
2550 }
2551 } // End SitAltitudeCallback KF.
2202 2552
2203 /// <summary> 2553 /// <summary>
2204 /// Event handler for the 'Always run' setting on the client 2554 /// Event handler for the 'Always run' setting on the client
@@ -2228,12 +2578,13 @@ namespace OpenSim.Region.Framework.Scenes
2228 /// </summary> 2578 /// </summary>
2229 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2579 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2230 /// <param name="rotation">The direction in which this avatar should now face. 2580 /// <param name="rotation">The direction in which this avatar should now face.
2231 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2581 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2232 { 2582 {
2233 if (m_isChildAgent) 2583 if (m_isChildAgent)
2234 { 2584 {
2235 // WHAT??? 2585 // WHAT???
2236 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); 2586 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent");
2587
2237 return; 2588 return;
2238 } 2589 }
2239 2590
@@ -2242,15 +2593,26 @@ namespace OpenSim.Region.Framework.Scenes
2242 Rotation = rotation; 2593 Rotation = rotation;
2243 Vector3 direc = vec * rotation; 2594 Vector3 direc = vec * rotation;
2244 direc.Normalize(); 2595 direc.Normalize();
2596 PhysicsActor actor = m_physicsActor;
2597
2598 if (actor.Flying != m_flyingOld) // add for fly velocity control
2599 {
2600 m_flyingOld = actor.Flying; // add for fly velocity control
2601 if (!actor.Flying) m_wasFlying = true; // add for fly velocity control
2602 }
2603
2604 if (m_physicsActor.IsColliding == true) m_wasFlying = false; // add for fly velocity control
2605
2606 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2245 2607
2246 direc *= 0.03f * 128f * m_speedModifier; 2608 direc *= 0.03f * 128f * m_speedModifier;
2247 2609
2248 PhysicsActor actor = m_physicsActor;
2249 if (actor != null) 2610 if (actor != null)
2250 { 2611 {
2251 if (actor.Flying) 2612 if (actor.Flying)
2252 { 2613 {
2253 direc *= 4.0f; 2614// rm speed mod direc *= 4.0f;
2615 direc *= 5.2f; // for speed mod
2254 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2616 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2255 //bool colliding = (m_physicsActor.IsColliding==true); 2617 //bool colliding = (m_physicsActor.IsColliding==true);
2256 //if (controlland) 2618 //if (controlland)
@@ -2263,22 +2625,34 @@ namespace OpenSim.Region.Framework.Scenes
2263 // m_log.Info("[AGENT]: Stop FLying"); 2625 // m_log.Info("[AGENT]: Stop FLying");
2264 //} 2626 //}
2265 } 2627 }
2628 if (Animator.m_falling && m_wasFlying) // if falling from flying, disable motion add
2629 {
2630 direc *= 0.0f;
2631 }
2632 /* This jumping section removed to SPA
2266 else if (!actor.Flying && actor.IsColliding) 2633 else if (!actor.Flying && actor.IsColliding)
2267 { 2634 {
2268 if (direc.Z > 2.0f) 2635 if (direc.Z > 2.0f)
2269 { 2636 {
2270 direc.Z *= 3.0f; 2637 if(m_animator.m_animTickJump == -1)
2271 2638 {
2272 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2639 direc.Z *= 3.0f; // jump
2273 Animator.TrySetMovementAnimation("PREJUMP"); 2640 }
2274 Animator.TrySetMovementAnimation("JUMP"); 2641 else
2642 {
2643 direc.Z *= 0.1f; // prejump
2644 }
2645 / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2646 Animator.TrySetMovementAnimation("PREJUMP");
2647 Animator.TrySetMovementAnimation("JUMP");
2648 * /
2275 } 2649 }
2276 } 2650 } */
2277 } 2651 }
2278 2652
2279 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2653 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2280 m_forceToApply = direc; 2654 m_forceToApply = direc;
2281 2655 m_isNudging = Nudging;
2282 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2656 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2283 } 2657 }
2284 2658
@@ -2327,6 +2701,9 @@ namespace OpenSim.Region.Framework.Scenes
2327 2701
2328 CheckForSignificantMovement(); // sends update to the modules. 2702 CheckForSignificantMovement(); // sends update to the modules.
2329 } 2703 }
2704
2705 //Sending prim updates AFTER the avatar terse updates are sent
2706 SendPrimUpdates();
2330 } 2707 }
2331 2708
2332 #endregion 2709 #endregion
@@ -3113,6 +3490,7 @@ namespace OpenSim.Region.Framework.Scenes
3113 m_callbackURI = cAgent.CallbackURI; 3490 m_callbackURI = cAgent.CallbackURI;
3114 3491
3115 m_pos = cAgent.Position; 3492 m_pos = cAgent.Position;
3493
3116 m_velocity = cAgent.Velocity; 3494 m_velocity = cAgent.Velocity;
3117 m_CameraCenter = cAgent.Center; 3495 m_CameraCenter = cAgent.Center;
3118 m_CameraAtAxis = cAgent.AtAxis; 3496 m_CameraAtAxis = cAgent.AtAxis;
@@ -3231,20 +3609,45 @@ namespace OpenSim.Region.Framework.Scenes
3231 /// </summary> 3609 /// </summary>
3232 public override void UpdateMovement() 3610 public override void UpdateMovement()
3233 { 3611 {
3234 if (m_forceToApply.HasValue) 3612 if (Animator!=null) // add for jumping
3235 { 3613 { // add for jumping
3236 Vector3 force = m_forceToApply.Value; 3614 // if (!m_animator.m_jumping) // add for jumping
3237 3615 // { // add for jumping
3238 m_updateflag = true;
3239 3616
3240 // The magic constant 0.95f seems to make walking feel less jerky, 3617 if (m_forceToApply.HasValue) // this section realigned
3241 // probably because it hackishly accounts for the overall latency of 3618 {
3242 // these Velocity updates -- Diva
3243 Velocity = force * .95F;
3244 3619
3245 m_forceToApply = null; 3620 Vector3 force = m_forceToApply.Value;
3246 } 3621 m_updateflag = true;
3247 } 3622if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3623 Velocity = force;
3624//Console.WriteLine("UM1 {0}", Velocity);
3625 m_forceToApply = null;
3626 }
3627 else
3628 {
3629 if (m_isNudging)
3630 {
3631 Vector3 force = Vector3.Zero;
3632
3633 m_updateflag = true;
3634if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3635 Velocity = force;
3636//Console.WriteLine("UM2 {0}", Velocity);
3637 m_isNudging = false;
3638 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3639 }
3640 else // add for jumping
3641 { // add for jumping
3642 Vector3 force = Vector3.Zero; // add for jumping
3643if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3644//Console.WriteLine("UM3 {0}", Velocity);
3645 Velocity = force; // add for jumping
3646 }
3647 }
3648 // } // end realign
3649 } // add for jumping
3650 } // add for jumping
3248 3651
3249 /// <summary> 3652 /// <summary>
3250 /// Adds a physical representation of the avatar to the Physics plugin 3653 /// Adds a physical representation of the avatar to the Physics plugin
@@ -3258,10 +3661,8 @@ namespace OpenSim.Region.Framework.Scenes
3258 3661
3259 Vector3 pVec = AbsolutePosition; 3662 Vector3 pVec = AbsolutePosition;
3260 3663
3261 // Old bug where the height was in centimeters instead of meters
3262 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, 3664 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3263 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3665 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3264
3265 scene.AddPhysicsActorTaint(m_physicsActor); 3666 scene.AddPhysicsActorTaint(m_physicsActor);
3266 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3667 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3267 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3668 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3285,18 +3686,29 @@ namespace OpenSim.Region.Framework.Scenes
3285 { 3686 {
3286 if (e == null) 3687 if (e == null)
3287 return; 3688 return;
3288 3689
3289 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3690 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3290 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3291 // as of this comment the interval is set in AddToPhysicalScene 3691 // as of this comment the interval is set in AddToPhysicalScene
3292 if (Animator!=null) 3692 if (Animator!=null)
3293 Animator.UpdateMovementAnimations(); 3693 {
3694 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3695 { // else its will lock out other animation changes, like ground sit.
3696 Animator.UpdateMovementAnimations();
3697 m_updateCount--;
3698 }
3699 }
3294 3700
3295 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3701 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3296 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3702 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3297 3703
3298 CollisionPlane = Vector4.UnitW; 3704 CollisionPlane = Vector4.UnitW;
3299 3705
3706 if (m_lastColCount != coldata.Count)
3707 {
3708 m_updateCount = UPDATE_COUNT;
3709 m_lastColCount = coldata.Count;
3710 }
3711
3300 if (coldata.Count != 0 && Animator != null) 3712 if (coldata.Count != 0 && Animator != null)
3301 { 3713 {
3302 switch (Animator.CurrentMovementAnimation) 3714 switch (Animator.CurrentMovementAnimation)
@@ -3326,6 +3738,148 @@ namespace OpenSim.Region.Framework.Scenes
3326 } 3738 }
3327 } 3739 }
3328 3740
3741 List<uint> thisHitColliders = new List<uint>();
3742 List<uint> endedColliders = new List<uint>();
3743 List<uint> startedColliders = new List<uint>();
3744
3745 foreach (uint localid in coldata.Keys)
3746 {
3747 thisHitColliders.Add(localid);
3748 if (!m_lastColliders.Contains(localid))
3749 {
3750 startedColliders.Add(localid);
3751 }
3752 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3753 }
3754
3755 // calculate things that ended colliding
3756 foreach (uint localID in m_lastColliders)
3757 {
3758 if (!thisHitColliders.Contains(localID))
3759 {
3760 endedColliders.Add(localID);
3761 }
3762 }
3763 //add the items that started colliding this time to the last colliders list.
3764 foreach (uint localID in startedColliders)
3765 {
3766 m_lastColliders.Add(localID);
3767 }
3768 // remove things that ended colliding from the last colliders list
3769 foreach (uint localID in endedColliders)
3770 {
3771 m_lastColliders.Remove(localID);
3772 }
3773
3774 // do event notification
3775 if (startedColliders.Count > 0)
3776 {
3777 ColliderArgs StartCollidingMessage = new ColliderArgs();
3778 List<DetectedObject> colliding = new List<DetectedObject>();
3779 foreach (uint localId in startedColliders)
3780 {
3781 if (localId == 0)
3782 continue;
3783
3784 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3785 string data = "";
3786 if (obj != null)
3787 {
3788 DetectedObject detobj = new DetectedObject();
3789 detobj.keyUUID = obj.UUID;
3790 detobj.nameStr = obj.Name;
3791 detobj.ownerUUID = obj.OwnerID;
3792 detobj.posVector = obj.AbsolutePosition;
3793 detobj.rotQuat = obj.GetWorldRotation();
3794 detobj.velVector = obj.Velocity;
3795 detobj.colliderType = 0;
3796 detobj.groupUUID = obj.GroupID;
3797 colliding.Add(detobj);
3798 }
3799 }
3800
3801 if (colliding.Count > 0)
3802 {
3803 StartCollidingMessage.Colliders = colliding;
3804
3805 foreach (SceneObjectGroup att in Attachments)
3806 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3807 }
3808 }
3809
3810 if (endedColliders.Count > 0)
3811 {
3812 ColliderArgs EndCollidingMessage = new ColliderArgs();
3813 List<DetectedObject> colliding = new List<DetectedObject>();
3814 foreach (uint localId in endedColliders)
3815 {
3816 if (localId == 0)
3817 continue;
3818
3819 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3820 string data = "";
3821 if (obj != null)
3822 {
3823 DetectedObject detobj = new DetectedObject();
3824 detobj.keyUUID = obj.UUID;
3825 detobj.nameStr = obj.Name;
3826 detobj.ownerUUID = obj.OwnerID;
3827 detobj.posVector = obj.AbsolutePosition;
3828 detobj.rotQuat = obj.GetWorldRotation();
3829 detobj.velVector = obj.Velocity;
3830 detobj.colliderType = 0;
3831 detobj.groupUUID = obj.GroupID;
3832 colliding.Add(detobj);
3833 }
3834 }
3835
3836 if (colliding.Count > 0)
3837 {
3838 EndCollidingMessage.Colliders = colliding;
3839
3840 foreach (SceneObjectGroup att in Attachments)
3841 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3842 }
3843 }
3844
3845 if (thisHitColliders.Count > 0)
3846 {
3847 ColliderArgs CollidingMessage = new ColliderArgs();
3848 List<DetectedObject> colliding = new List<DetectedObject>();
3849 foreach (uint localId in thisHitColliders)
3850 {
3851 if (localId == 0)
3852 continue;
3853
3854 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3855 string data = "";
3856 if (obj != null)
3857 {
3858 DetectedObject detobj = new DetectedObject();
3859 detobj.keyUUID = obj.UUID;
3860 detobj.nameStr = obj.Name;
3861 detobj.ownerUUID = obj.OwnerID;
3862 detobj.posVector = obj.AbsolutePosition;
3863 detobj.rotQuat = obj.GetWorldRotation();
3864 detobj.velVector = obj.Velocity;
3865 detobj.colliderType = 0;
3866 detobj.groupUUID = obj.GroupID;
3867 colliding.Add(detobj);
3868 }
3869 }
3870
3871 if (colliding.Count > 0)
3872 {
3873 CollidingMessage.Colliders = colliding;
3874
3875 lock (m_attachments)
3876 {
3877 foreach (SceneObjectGroup att in m_attachments)
3878 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3879 }
3880 }
3881 }
3882
3329 if (m_invulnerable) 3883 if (m_invulnerable)
3330 return; 3884 return;
3331 3885
@@ -3751,6 +4305,39 @@ namespace OpenSim.Region.Framework.Scenes
3751 return; 4305 return;
3752 } 4306 }
3753 4307
4308 XmlDocument doc = new XmlDocument();
4309 string stateData = String.Empty;
4310
4311 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4312 if (attServ != null)
4313 {
4314 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4315 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4316 if (stateData != String.Empty)
4317 {
4318 try
4319 {
4320 doc.LoadXml(stateData);
4321 }
4322 catch { }
4323 }
4324 }
4325
4326 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4327
4328 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4329 if (nodes.Count > 0)
4330 {
4331 foreach (XmlNode n in nodes)
4332 {
4333 XmlElement elem = (XmlElement)n;
4334 string itemID = elem.GetAttribute("ItemID");
4335 string xml = elem.InnerXml;
4336
4337 itemData[new UUID(itemID)] = xml;
4338 }
4339 }
4340
3754 List<AvatarAttachment> attachments = m_appearance.GetAttachments(); 4341 List<AvatarAttachment> attachments = m_appearance.GetAttachments();
3755 foreach (AvatarAttachment attach in attachments) 4342 foreach (AvatarAttachment attach in attachments)
3756 { 4343 {
@@ -3771,7 +4358,30 @@ namespace OpenSim.Region.Framework.Scenes
3771 4358
3772 try 4359 try
3773 { 4360 {
3774 m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4361 string xmlData;
4362 XmlDocument d = new XmlDocument();
4363 UUID asset;
4364 if (itemData.TryGetValue(itemID, out xmlData))
4365 {
4366 d.LoadXml(xmlData);
4367 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4368
4369 // Rez from inventory
4370 asset
4371 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4372
4373 }
4374 else
4375 {
4376 // Rez from inventory (with a null doc to let
4377 // CHANGED_OWNER happen)
4378 asset
4379 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4380 }
4381
4382 m_log.InfoFormat(
4383 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}",
4384 p, itemID, asset);
3775 } 4385 }
3776 catch (Exception e) 4386 catch (Exception e)
3777 { 4387 {
@@ -3804,6 +4414,15 @@ namespace OpenSim.Region.Framework.Scenes
3804 m_reprioritization_called = false; 4414 m_reprioritization_called = false;
3805 } 4415 }
3806 } 4416 }
4417
4418 private Vector3 Quat2Euler(Quaternion rot){
4419 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4420 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4421 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4422 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4423 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4424 return(new Vector3(x,y,z));
4425 }
3807 4426
3808 public void SaveChangedAttachments() 4427 public void SaveChangedAttachments()
3809 { 4428 {
@@ -3827,5 +4446,30 @@ namespace OpenSim.Region.Framework.Scenes
3827 } 4446 }
3828 } 4447 }
3829 } 4448 }
4449
4450 private void CheckLandingPoint(ref Vector3 pos)
4451 {
4452 // Never constrain lures
4453 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
4454 return;
4455
4456 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
4457 return;
4458
4459 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
4460
4461 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
4462 land.LandData.UserLocation != Vector3.Zero &&
4463 land.LandData.OwnerID != m_uuid &&
4464 (!m_scene.Permissions.IsGod(m_uuid)) &&
4465 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)))
4466 {
4467 float curr = Vector3.Distance(AbsolutePosition, pos);
4468 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
4469 pos = land.LandData.UserLocation;
4470 else
4471 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
4472 }
4473 }
3830 } 4474 }
3831} 4475}
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
index 7c067ca..1f4ec96 100644
--- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
@@ -106,7 +106,7 @@ namespace OpenSim.Region.Framework.Scenes
106 g.ScheduleFullUpdateToAvatar(m_presence); 106 g.ScheduleFullUpdateToAvatar(m_presence);
107 } 107 }
108 108
109 while (m_partsUpdateQueue.Count > 0) 109 while (m_partsUpdateQueue.Count != null && m_partsUpdateQueue.Count > 0)
110 { 110 {
111 SceneObjectPart part = m_partsUpdateQueue.Dequeue(); 111 SceneObjectPart part = m_partsUpdateQueue.Dequeue();
112 112
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 57ae4fd..b2b3ad9 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -102,7 +102,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
102 sceneObject.AddPart(part); 102 sceneObject.AddPart(part);
103 part.LinkNum = linkNum; 103 part.LinkNum = linkNum;
104 part.TrimPermissions(); 104 part.TrimPermissions();
105 part.StoreUndoState(); 105 part.StoreUndoState(UndoType.STATE_ALL);
106 reader.Close(); 106 reader.Close();
107 sr.Close(); 107 sr.Close();
108 } 108 }
@@ -220,7 +220,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
220 if (originalLinkNum != 0) 220 if (originalLinkNum != 0)
221 part.LinkNum = originalLinkNum; 221 part.LinkNum = originalLinkNum;
222 222
223 part.StoreUndoState(); 223 part.StoreUndoState(UndoType.STATE_ALL);
224 reader.Close(); 224 reader.Close();
225 sr.Close(); 225 sr.Close();
226 } 226 }
@@ -1441,12 +1441,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1441 { 1441 {
1442 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1442 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1443 1443
1444 if (reader.IsEmptyElement)
1445 {
1446 reader.Read();
1447 return tinv;
1448 }
1449
1450 reader.ReadStartElement(name, String.Empty); 1444 reader.ReadStartElement(name, String.Empty);
1451 1445
1452 while (reader.Name == "TaskInventoryItem") 1446 while (reader.Name == "TaskInventoryItem")
@@ -1480,12 +1474,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1480 { 1474 {
1481 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1475 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1482 1476
1483 if (reader.IsEmptyElement)
1484 {
1485 reader.Read();
1486 return shape;
1487 }
1488
1489 reader.ReadStartElement(name, String.Empty); // Shape 1477 reader.ReadStartElement(name, String.Empty); // Shape
1490 1478
1491 string nodeName = string.Empty; 1479 string nodeName = string.Empty;
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 55e407e..f71b507 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -27,48 +27,125 @@
27 27
28using OpenMetaverse; 28using OpenMetaverse;
29using OpenSim.Region.Framework.Interfaces; 29using OpenSim.Region.Framework.Interfaces;
30using System;
30 31
31namespace OpenSim.Region.Framework.Scenes 32namespace OpenSim.Region.Framework.Scenes
32{ 33{
34 [Flags]
35 public enum UndoType
36 {
37 STATE_PRIM_POSITION = 1,
38 STATE_PRIM_ROTATION = 2,
39 STATE_PRIM_SCALE = 4,
40 STATE_PRIM_ALL = 7,
41 STATE_GROUP_POSITION = 8,
42 STATE_GROUP_ROTATION = 16,
43 STATE_GROUP_SCALE = 32,
44 STATE_GROUP_ALL = 56,
45 STATE_ALL = 63
46 }
47
33 public class UndoState 48 public class UndoState
34 { 49 {
35 public Vector3 Position = Vector3.Zero; 50 public Vector3 Position = Vector3.Zero;
36 public Vector3 Scale = Vector3.Zero; 51 public Vector3 Scale = Vector3.Zero;
37 public Quaternion Rotation = Quaternion.Identity; 52 public Quaternion Rotation = Quaternion.Identity;
53 public Vector3 GroupPosition = Vector3.Zero;
54 public Quaternion GroupRotation = Quaternion.Identity;
55 public Vector3 GroupScale = Vector3.Zero;
56 public DateTime LastUpdated = DateTime.Now;
57 public UndoType Type;
38 58
39 public UndoState(SceneObjectPart part) 59 public UndoState(SceneObjectPart part, UndoType type)
40 { 60 {
61 Type = type;
41 if (part != null) 62 if (part != null)
42 { 63 {
43 if (part.ParentID == 0) 64 if (part.ParentID == 0)
44 { 65 {
45 Position = part.ParentGroup.AbsolutePosition; 66 GroupScale = part.ParentGroup.RootPart.Shape.Scale;
67
68 //FUBAR WARNING: Do NOT get the group's absoluteposition here
69 //or you'll experience a loop and/or a stack issue
70 GroupPosition = part.ParentGroup.RootPart.AbsolutePosition;
71 GroupRotation = part.ParentGroup.GroupRotation;
72 Position = part.ParentGroup.RootPart.AbsolutePosition;
46 Rotation = part.RotationOffset; 73 Rotation = part.RotationOffset;
47 Scale = part.Shape.Scale; 74 Scale = part.Shape.Scale;
75 LastUpdated = DateTime.Now;
48 } 76 }
49 else 77 else
50 { 78 {
79 GroupScale = part.Shape.Scale;
80
81 //FUBAR WARNING: Do NOT get the group's absoluteposition here
82 //or you'll experience a loop and/or a stack issue
83 GroupPosition = part.ParentGroup.RootPart.AbsolutePosition;
84 GroupRotation = part.ParentGroup.Rotation;
51 Position = part.OffsetPosition; 85 Position = part.OffsetPosition;
52 Rotation = part.RotationOffset; 86 Rotation = part.RotationOffset;
53 Scale = part.Shape.Scale; 87 Scale = part.Shape.Scale;
88 LastUpdated = DateTime.Now;
54 } 89 }
55 } 90 }
56 } 91 }
57 92 public void Merge(UndoState last)
93 {
94 if ((Type & UndoType.STATE_GROUP_POSITION) == 0 || ((last.Type & UndoType.STATE_GROUP_POSITION) >= (Type & UndoType.STATE_GROUP_POSITION)))
95 {
96 GroupPosition = last.GroupPosition;
97 Position = last.Position;
98 }
99 if ((Type & UndoType.STATE_GROUP_SCALE) == 0 || ((last.Type & UndoType.STATE_GROUP_SCALE) >= (Type & UndoType.STATE_GROUP_SCALE)))
100 {
101 GroupScale = last.GroupScale;
102 Scale = last.Scale;
103 }
104 if ((Type & UndoType.STATE_GROUP_ROTATION) == 0 || ((last.Type & UndoType.STATE_GROUP_ROTATION) >= (Type & UndoType.STATE_GROUP_ROTATION)))
105 {
106 GroupRotation = last.GroupRotation;
107 Rotation = last.Rotation;
108 }
109 if ((Type & UndoType.STATE_PRIM_POSITION) == 0 || ((last.Type & UndoType.STATE_PRIM_POSITION) >= (Type & UndoType.STATE_PRIM_POSITION)))
110 {
111 Position = last.Position;
112 }
113 if ((Type & UndoType.STATE_PRIM_SCALE) == 0 || ((last.Type & UndoType.STATE_PRIM_SCALE) >= (Type & UndoType.STATE_PRIM_SCALE)))
114 {
115 Scale = last.Scale;
116 }
117 if ((Type & UndoType.STATE_PRIM_ROTATION) == 0 || ((last.Type & UndoType.STATE_PRIM_ROTATION) >= (Type & UndoType.STATE_PRIM_ROTATION)))
118 {
119 Rotation = last.Rotation;
120 }
121 Type = Type | last.Type;
122 }
123 public bool Compare(UndoState undo)
124 {
125 if (undo == null || Position == null) return false;
126 if (undo.Position == Position && undo.Rotation == Rotation && undo.Scale == Scale && undo.GroupPosition == GroupPosition && undo.GroupScale == GroupScale && undo.GroupRotation == GroupRotation)
127 {
128 return true;
129 }
130 else
131 {
132 return false;
133 }
134 }
58 public bool Compare(SceneObjectPart part) 135 public bool Compare(SceneObjectPart part)
59 { 136 {
60 if (part != null) 137 if (part != null)
61 { 138 {
62 if (part.ParentID == 0) 139 if (part.ParentID == 0)
63 { 140 {
64 if (Position == part.ParentGroup.AbsolutePosition && Rotation == part.ParentGroup.Rotation) 141 if (Position == part.ParentGroup.RootPart.AbsolutePosition && Rotation == part.ParentGroup.Rotation && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale)
65 return true; 142 return true;
66 else 143 else
67 return false; 144 return false;
68 } 145 }
69 else 146 else
70 { 147 {
71 if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale) 148 if (Position == part.OffsetPosition && Rotation == part.RotationOffset && Scale == part.Shape.Scale && GroupPosition == part.ParentGroup.RootPart.AbsolutePosition && part.ParentGroup.Rotation == GroupRotation && part.Shape.Scale == GroupScale)
72 return true; 149 return true;
73 else 150 else
74 return false; 151 return false;
@@ -78,62 +155,70 @@ namespace OpenSim.Region.Framework.Scenes
78 return false; 155 return false;
79 } 156 }
80 157
81 public void PlaybackState(SceneObjectPart part) 158 private void RestoreState(SceneObjectPart part)
82 { 159 {
160 bool GroupChange = false;
161 if ((Type & UndoType.STATE_GROUP_POSITION) != 0
162 || (Type & UndoType.STATE_GROUP_ROTATION) != 0
163 || (Type & UndoType.STATE_GROUP_SCALE) != 0)
164 {
165 GroupChange = true;
166 }
167
83 if (part != null) 168 if (part != null)
84 { 169 {
85 part.Undoing = true; 170 part.Undoing = true;
86 171
87 if (part.ParentID == 0) 172 if (part.ParentID == 0 && GroupChange == false)
88 { 173 {
89 if (Position != Vector3.Zero) 174 if (Position != Vector3.Zero)
90 part.ParentGroup.AbsolutePosition = Position; 175
91 part.RotationOffset = Rotation; 176 part.ParentGroup.UpdateSinglePosition(Position, part.LocalId);
177 part.ParentGroup.UpdateSingleRotation(Rotation, part.LocalId);
92 if (Scale != Vector3.Zero) 178 if (Scale != Vector3.Zero)
93 part.Resize(Scale); 179 part.Resize(Scale);
94 part.ParentGroup.ScheduleGroupForTerseUpdate(); 180 part.ParentGroup.ScheduleGroupForTerseUpdate();
95 } 181 }
96 else 182 else
97 { 183 {
98 if (Position != Vector3.Zero) 184 if (GroupChange)
99 part.OffsetPosition = Position; 185 {
100 part.UpdateRotation(Rotation); 186 part.ParentGroup.RootPart.Undoing = true;
101 if (Scale != Vector3.Zero) 187 if (GroupPosition != Vector3.Zero)
102 part.Resize(Scale); part.ScheduleTerseUpdate(); 188 {
189 //Calculate the scale...
190 Vector3 gs = part.Shape.Scale;
191 float scale = GroupScale.Z / gs.Z;
192
193 //Scale first since it can affect our position
194 part.ParentGroup.GroupResize(gs * scale, part.LocalId);
195 part.ParentGroup.AbsolutePosition = GroupPosition;
196 part.ParentGroup.UpdateGroupRotationR(GroupRotation);
197
198 }
199 part.ParentGroup.RootPart.Undoing = false;
200 }
201 else
202 {
203 if (Position != Vector3.Zero) //We can use this for all the updates since all are set
204 {
205 part.OffsetPosition = Position;
206 part.UpdateRotation(Rotation);
207 part.Resize(Scale); part.ScheduleTerseUpdate();
208 }
209 }
103 } 210 }
104 part.Undoing = false; 211 part.Undoing = false;
105 212
106 } 213 }
107 } 214 }
215 public void PlaybackState(SceneObjectPart part)
216 {
217 RestoreState(part);
218 }
108 public void PlayfwdState(SceneObjectPart part) 219 public void PlayfwdState(SceneObjectPart part)
109 { 220 {
110 if (part != null) 221 RestoreState(part);
111 {
112 part.Undoing = true;
113
114 if (part.ParentID == 0)
115 {
116 if (Position != Vector3.Zero)
117 part.ParentGroup.AbsolutePosition = Position;
118 if (Rotation != Quaternion.Identity)
119 part.UpdateRotation(Rotation);
120 if (Scale != Vector3.Zero)
121 part.Resize(Scale);
122 part.ParentGroup.ScheduleGroupForTerseUpdate();
123 }
124 else
125 {
126 if (Position != Vector3.Zero)
127 part.OffsetPosition = Position;
128 if (Rotation != Quaternion.Identity)
129 part.UpdateRotation(Rotation);
130 if (Scale != Vector3.Zero)
131 part.Resize(Scale);
132 part.ScheduleTerseUpdate();
133 }
134 part.Undoing = false;
135
136 }
137 } 222 }
138 } 223 }
139 public class LandUndoState 224 public class LandUndoState
@@ -161,3 +246,4 @@ namespace OpenSim.Region.Framework.Scenes
161 } 246 }
162 } 247 }
163} 248}
249
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index 83906d7..3978a7d 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -86,10 +86,6 @@ namespace OpenSim.Region.Framework.Scenes
86 /// <param name="assetUuids">The assets gathered</param> 86 /// <param name="assetUuids">The assets gathered</param>
87 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 87 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
88 { 88 {
89 // avoid infinite loops
90 if (assetUuids.ContainsKey(assetUuid))
91 return;
92
93 try 89 try
94 { 90 {
95 assetUuids[assetUuid] = assetType; 91 assetUuids[assetUuid] = assetType;