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/IEstateModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IInterregionComms.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISnmpModule.cs27
-rw-r--r--OpenSim/Region/Framework/Interfaces/IUserAccountCacheModule.cs13
-rw-r--r--OpenSim/Region/Framework/ModuleLoader.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs226
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs8
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs267
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs504
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs50
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs219
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs700
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs301
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs756
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs1071
-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
28 files changed, 3220 insertions, 1209 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/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
index 721f0ee..72e79ed 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs
@@ -45,5 +45,7 @@ namespace OpenSim.Region.Framework.Interfaces
45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.). 45 /// Tell all clients about the current state of the region (terrain textures, water height, etc.).
46 /// </summary> 46 /// </summary>
47 void sendRegionHandshakeToAll(); 47 void sendRegionHandshakeToAll();
48 void TriggerEstateInfoChange();
49 void TriggerRegionInfoChange();
48 } 50 }
49} 51}
diff --git a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
index 2d6287f..67a500f 100644
--- a/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
+++ b/OpenSim/Region/Framework/Interfaces/IInterregionComms.cs
@@ -68,6 +68,14 @@ namespace OpenSim.Region.Framework.Interfaces
68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri); 68 bool SendReleaseAgent(ulong regionHandle, UUID id, string uri);
69 69
70 /// <summary> 70 /// <summary>
71 /// Close chid agent.
72 /// </summary>
73 /// <param name="regionHandle"></param>
74 /// <param name="id"></param>
75 /// <returns></returns>
76 bool SendCloseChildAgent(ulong regionHandle, UUID id);
77
78 /// <summary>
71 /// Close agent. 79 /// Close agent.
72 /// </summary> 80 /// </summary>
73 /// <param name="regionHandle"></param> 81 /// <param name="regionHandle"></param>
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index 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 14ecd44..32ee674 100644
--- a/OpenSim/Region/Framework/ModuleLoader.cs
+++ b/OpenSim/Region/Framework/ModuleLoader.cs
@@ -227,7 +227,8 @@ namespace OpenSim.Region.Framework
227 pluginAssembly.FullName, e.Message, e.StackTrace); 227 pluginAssembly.FullName, e.Message, e.StackTrace);
228 228
229 // justincc: Right now this is fatal to really get the user's attention 229 // justincc: Right now this is fatal to really get the user's attention
230 throw e; 230 // TomMeta: WTF? No, how about we /don't/ throw a fatal exception when there's no need to?
231 //throw e;
231 } 232 }
232 } 233 }
233 234
diff --git a/OpenSim/Region/Framework/Scenes/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 3423542..088839d 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,8 +104,15 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
107 foreach (SceneObjectGroup g in objectGroups) 109 foreach (SceneObjectGroup g in objectGroups)
110 {
111 killIDs.Add(g.LocalId);
108 g.DeleteGroupFromScene(false); 112 g.DeleteGroupFromScene(false);
113 }
114
115 m_scene.SendKillObject(killIDs);
109 } 116 }
110 } 117 }
111 118
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index fd62535..4ce7a6c 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;
@@ -766,6 +770,26 @@ namespace OpenSim.Region.Framework.Scenes
766 } 770 }
767 } 771 }
768 } 772 }
773 public void TriggerTerrainUpdate()
774 {
775 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
776 if (handlerTerrainUpdate != null)
777 {
778 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
779 {
780 try
781 {
782 d();
783 }
784 catch (Exception e)
785 {
786 m_log.ErrorFormat(
787 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
788 e.Message, e.StackTrace);
789 }
790 }
791 }
792 }
769 793
770 public void TriggerTerrainTick() 794 public void TriggerTerrainTick()
771 { 795 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 4595a29..0f35894 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -158,6 +158,8 @@ namespace OpenSim.Region.Framework.Scenes
158 158
159 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 159 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
160 { 160 {
161 if (entity == null) return 0;
162
161 uint pqueue = ComputeDistancePriority(client,entity,true); 163 uint pqueue = ComputeDistancePriority(client,entity,true);
162 164
163 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 165 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
@@ -188,6 +190,12 @@ namespace OpenSim.Region.Framework.Scenes
188 190
189 private uint ComputeDistancePriority(IClientAPI client, ISceneEntity entity, bool useFrontBack) 191 private uint ComputeDistancePriority(IClientAPI client, ISceneEntity entity, bool useFrontBack)
190 { 192 {
193 // If this is an update for our own avatar give it the highest priority
194 if (client.AgentId == entity.UUID)
195 return 0;
196 if (entity == null)
197 return 0;
198
191 // Get this agent's position 199 // Get this agent's position
192 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 200 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
193 if (presence == null) 201 if (presence == null)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index b0f0de6..5b7a297 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;
@@ -328,6 +310,7 @@ namespace OpenSim.Region.Framework.Scenes
328 { 310 {
329 if (UUID.Zero == transactionID) 311 if (UUID.Zero == transactionID)
330 { 312 {
313 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
331 item.Name = itemUpd.Name; 314 item.Name = itemUpd.Name;
332 item.Description = itemUpd.Description; 315 item.Description = itemUpd.Description;
333 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 316 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -700,6 +683,8 @@ namespace OpenSim.Region.Framework.Scenes
700 return; 683 return;
701 } 684 }
702 685
686 if (newName == null) newName = item.Name;
687
703 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 688 AssetBase asset = AssetService.Get(item.AssetID.ToString());
704 689
705 if (asset != null) 690 if (asset != null)
@@ -753,6 +738,24 @@ namespace OpenSim.Region.Framework.Scenes
753 } 738 }
754 739
755 /// <summary> 740 /// <summary>
741 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
742 /// </summary>
743 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
744 {
745 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
746 foreach (InventoryItemBase b in items)
747 {
748 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
749 InventoryItemBase n = InventoryService.GetItem(b);
750 n.Folder = destfolder;
751 moveitems.Add(n);
752 remoteClient.SendInventoryItemCreateUpdate(n, 0);
753 }
754
755 MoveInventoryItem(remoteClient, moveitems);
756 }
757
758 /// <summary>
756 /// Move an item within the agent's inventory. 759 /// Move an item within the agent's inventory.
757 /// </summary> 760 /// </summary>
758 /// <param name="remoteClient"></param> 761 /// <param name="remoteClient"></param>
@@ -985,8 +988,12 @@ namespace OpenSim.Region.Framework.Scenes
985 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 988 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
986 { 989 {
987 SceneObjectPart part = GetSceneObjectPart(localID); 990 SceneObjectPart part = GetSceneObjectPart(localID);
988 SceneObjectGroup group = part.ParentGroup; 991 SceneObjectGroup group = null;
989 if (group != null) 992 if (part != null)
993 {
994 group = part.ParentGroup;
995 }
996 if (part != null && group != null)
990 { 997 {
991 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 998 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
992 return; 999 return;
@@ -1222,6 +1229,10 @@ namespace OpenSim.Region.Framework.Scenes
1222 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1229 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1223 return; 1230 return;
1224 1231
1232 bool overrideNoMod = false;
1233 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1234 overrideNoMod = true;
1235
1225 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1236 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1226 { 1237 {
1227 // object cannot copy items to an object owned by a different owner 1238 // object cannot copy items to an object owned by a different owner
@@ -1231,7 +1242,7 @@ namespace OpenSim.Region.Framework.Scenes
1231 } 1242 }
1232 1243
1233 // must have both move and modify permission to put an item in an object 1244 // must have both move and modify permission to put an item in an object
1234 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1245 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1235 { 1246 {
1236 return; 1247 return;
1237 } 1248 }
@@ -1290,6 +1301,14 @@ namespace OpenSim.Region.Framework.Scenes
1290 1301
1291 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1302 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1292 { 1303 {
1304 SceneObjectPart destPart = GetSceneObjectPart(destID);
1305 if (destPart != null) // Move into a prim
1306 {
1307 foreach(UUID itemID in items)
1308 MoveTaskInventoryItem(destID, host, itemID);
1309 return destID; // Prim folder ID == prim ID
1310 }
1311
1293 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1312 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1294 1313
1295 UUID newFolderID = UUID.Random(); 1314 UUID newFolderID = UUID.Random();
@@ -1439,13 +1458,6 @@ namespace OpenSim.Region.Framework.Scenes
1439 { 1458 {
1440 agentTransactions.HandleTaskItemUpdateFromTransaction( 1459 agentTransactions.HandleTaskItemUpdateFromTransaction(
1441 remoteClient, part, transactionID, currentItem); 1460 remoteClient, part, transactionID, currentItem);
1442
1443 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1444 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1445 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1446 remoteClient.SendAgentAlertMessage("Script saved", false);
1447 else
1448 remoteClient.SendAgentAlertMessage("Item saved", false);
1449 } 1461 }
1450 1462
1451 // Base ALWAYS has move 1463 // Base ALWAYS has move
@@ -1586,7 +1598,7 @@ namespace OpenSim.Region.Framework.Scenes
1586 return; 1598 return;
1587 1599
1588 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1600 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1589 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1601 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1590 remoteClient.AgentId); 1602 remoteClient.AgentId);
1591 AssetService.Store(asset); 1603 AssetService.Store(asset);
1592 1604
@@ -1739,23 +1751,32 @@ namespace OpenSim.Region.Framework.Scenes
1739 // build a list of eligible objects 1751 // build a list of eligible objects
1740 List<uint> deleteIDs = new List<uint>(); 1752 List<uint> deleteIDs = new List<uint>();
1741 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1753 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1742 1754 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1743 // Start with true for both, then remove the flags if objects
1744 // that we can't derez are part of the selection
1745 bool permissionToTake = true;
1746 bool permissionToTakeCopy = true;
1747 bool permissionToDelete = true;
1748 1755
1749 foreach (uint localID in localIDs) 1756 foreach (uint localID in localIDs)
1750 { 1757 {
1758 // Start with true for both, then remove the flags if objects
1759 // that we can't derez are part of the selection
1760 bool permissionToTake = true;
1761 bool permissionToTakeCopy = true;
1762 bool permissionToDelete = true;
1763
1751 // Invalid id 1764 // Invalid id
1752 SceneObjectPart part = GetSceneObjectPart(localID); 1765 SceneObjectPart part = GetSceneObjectPart(localID);
1753 if (part == null) 1766 if (part == null)
1767 {
1768 //Client still thinks the object exists, kill it
1769 deleteIDs.Add(localID);
1754 continue; 1770 continue;
1771 }
1755 1772
1756 // Already deleted by someone else 1773 // Already deleted by someone else
1757 if (part.ParentGroup == null || part.ParentGroup.IsDeleted) 1774 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
1775 {
1776 //Client still thinks the object exists, kill it
1777 deleteIDs.Add(localID);
1758 continue; 1778 continue;
1779 }
1759 1780
1760 // Can't delete child prims 1781 // Can't delete child prims
1761 if (part != part.ParentGroup.RootPart) 1782 if (part != part.ParentGroup.RootPart)
@@ -1763,9 +1784,6 @@ namespace OpenSim.Region.Framework.Scenes
1763 1784
1764 SceneObjectGroup grp = part.ParentGroup; 1785 SceneObjectGroup grp = part.ParentGroup;
1765 1786
1766 deleteIDs.Add(localID);
1767 deleteGroups.Add(grp);
1768
1769 if (remoteClient == null) 1787 if (remoteClient == null)
1770 { 1788 {
1771 // Autoreturn has a null client. Nothing else does. So 1789 // Autoreturn has a null client. Nothing else does. So
@@ -1782,80 +1800,104 @@ namespace OpenSim.Region.Framework.Scenes
1782 } 1800 }
1783 else 1801 else
1784 { 1802 {
1785 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1803 if (action == DeRezAction.TakeCopy)
1804 {
1805 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1806 permissionToTakeCopy = false;
1807 }
1808 else
1809 {
1786 permissionToTakeCopy = false; 1810 permissionToTakeCopy = false;
1787 1811 }
1788 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1812 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1789 permissionToTake = false; 1813 permissionToTake = false;
1790 1814
1791 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1815 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1792 permissionToDelete = false; 1816 permissionToDelete = false;
1793 } 1817 }
1794 }
1795 1818
1796 // Handle god perms 1819 // Handle god perms
1797 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1820 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1798 { 1821 {
1799 permissionToTake = true; 1822 permissionToTake = true;
1800 permissionToTakeCopy = true; 1823 permissionToTakeCopy = true;
1801 permissionToDelete = true; 1824 permissionToDelete = true;
1802 } 1825 }
1803 1826
1804 // If we're re-saving, we don't even want to delete 1827 // If we're re-saving, we don't even want to delete
1805 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1828 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1806 permissionToDelete = false; 1829 permissionToDelete = false;
1807 1830
1808 // if we want to take a copy, we also don't want to delete 1831 // if we want to take a copy, we also don't want to delete
1809 // Note: after this point, the permissionToTakeCopy flag 1832 // Note: after this point, the permissionToTakeCopy flag
1810 // becomes irrelevant. It already includes the permissionToTake 1833 // becomes irrelevant. It already includes the permissionToTake
1811 // permission and after excluding no copy items here, we can 1834 // permission and after excluding no copy items here, we can
1812 // just use that. 1835 // just use that.
1813 if (action == DeRezAction.TakeCopy) 1836 if (action == DeRezAction.TakeCopy)
1814 { 1837 {
1815 // If we don't have permission, stop right here 1838 // If we don't have permission, stop right here
1816 if (!permissionToTakeCopy) 1839 if (!permissionToTakeCopy)
1817 return; 1840 return;
1818 1841
1819 permissionToTake = true; 1842 permissionToTake = true;
1820 // Don't delete 1843 // Don't delete
1821 permissionToDelete = false; 1844 permissionToDelete = false;
1822 } 1845 }
1823 1846
1824 if (action == DeRezAction.Return) 1847 if (action == DeRezAction.Return)
1825 {
1826 if (remoteClient != null)
1827 { 1848 {
1828 if (Permissions.CanReturnObjects( 1849 if (remoteClient != null)
1829 null,
1830 remoteClient.AgentId,
1831 deleteGroups))
1832 { 1850 {
1833 permissionToTake = true; 1851 if (Permissions.CanReturnObjects(
1834 permissionToDelete = true; 1852 null,
1835 1853 remoteClient.AgentId,
1836 foreach (SceneObjectGroup g in deleteGroups) 1854 deleteGroups))
1837 { 1855 {
1838 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1856 permissionToTake = true;
1857 permissionToDelete = true;
1858
1859 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1839 } 1860 }
1840 } 1861 }
1862 else // Auto return passes through here with null agent
1863 {
1864 permissionToTake = true;
1865 permissionToDelete = true;
1866 }
1841 } 1867 }
1842 else // Auto return passes through here with null agent 1868
1869 if (permissionToTake && (!permissionToDelete))
1870 takeGroups.Add(grp);
1871
1872 if (permissionToDelete)
1843 { 1873 {
1844 permissionToTake = true; 1874 if (permissionToTake)
1845 permissionToDelete = true; 1875 deleteGroups.Add(grp);
1876 deleteIDs.Add(grp.LocalId);
1846 } 1877 }
1847 } 1878 }
1848 1879
1849 if (permissionToTake) 1880 SendKillObject(deleteIDs);
1881
1882 if (deleteGroups.Count > 0)
1850 { 1883 {
1884 foreach (SceneObjectGroup g in deleteGroups)
1885 deleteIDs.Remove(g.LocalId);
1886
1851 m_asyncSceneObjectDeleter.DeleteToInventory( 1887 m_asyncSceneObjectDeleter.DeleteToInventory(
1852 action, destinationID, deleteGroups, remoteClient, 1888 action, destinationID, deleteGroups, remoteClient,
1853 permissionToDelete); 1889 true);
1890 }
1891 if (takeGroups.Count > 0)
1892 {
1893 m_asyncSceneObjectDeleter.DeleteToInventory(
1894 action, destinationID, takeGroups, remoteClient,
1895 false);
1854 } 1896 }
1855 else if (permissionToDelete) 1897 if (deleteIDs.Count > 0)
1856 { 1898 {
1857 foreach (SceneObjectGroup g in deleteGroups) 1899 foreach (SceneObjectGroup g in deleteGroups)
1858 DeleteSceneObject(g, false); 1900 DeleteSceneObject(g, true);
1859 } 1901 }
1860 } 1902 }
1861 1903
@@ -1907,21 +1949,29 @@ namespace OpenSim.Region.Framework.Scenes
1907 else // oopsies 1949 else // oopsies
1908 item.Folder = UUID.Zero; 1950 item.Folder = UUID.Zero;
1909 1951
1952 // Set up base perms properly
1953 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1954 permsBase &= grp.RootPart.BaseMask;
1955 permsBase |= (uint)PermissionMask.Move;
1956
1957 // Make sure we don't lock it
1958 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1959
1910 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions()) 1960 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1911 { 1961 {
1912 item.BasePermissions = grp.RootPart.NextOwnerMask; 1962 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1913 item.CurrentPermissions = grp.RootPart.NextOwnerMask; 1963 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1914 item.NextPermissions = grp.RootPart.NextOwnerMask; 1964 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1915 item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask; 1965 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1916 item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask; 1966 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1917 } 1967 }
1918 else 1968 else
1919 { 1969 {
1920 item.BasePermissions = grp.RootPart.BaseMask; 1970 item.BasePermissions = permsBase;
1921 item.CurrentPermissions = grp.RootPart.OwnerMask; 1971 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1922 item.NextPermissions = grp.RootPart.NextOwnerMask; 1972 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1923 item.EveryOnePermissions = grp.RootPart.EveryoneMask; 1973 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1924 item.GroupPermissions = grp.RootPart.GroupMask; 1974 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1925 } 1975 }
1926 item.CreationDate = Util.UnixTimeSinceEpoch(); 1976 item.CreationDate = Util.UnixTimeSinceEpoch();
1927 1977
@@ -2077,6 +2127,9 @@ namespace OpenSim.Region.Framework.Scenes
2077 2127
2078 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2128 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2079 { 2129 {
2130 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2131 return;
2132
2080 SceneObjectPart part = GetSceneObjectPart(objectID); 2133 SceneObjectPart part = GetSceneObjectPart(objectID);
2081 if (part == null) 2134 if (part == null)
2082 return; 2135 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 2cbe4dc..1d06889 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -93,6 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
93 // TODO: need to figure out how allow client agents but deny 93 // TODO: need to figure out how allow client agents but deny
94 // root agents when ACL denies access to root agent 94 // root agents when ACL denies access to root agent
95 public bool m_strictAccessControl = true; 95 public bool m_strictAccessControl = true;
96 public bool m_seeIntoBannedRegion = false;
96 public int MaxUndoCount = 5; 97 public int MaxUndoCount = 5;
97 public bool LoginsDisabled = true; 98 public bool LoginsDisabled = true;
98 public bool LoadingPrims; 99 public bool LoadingPrims;
@@ -111,6 +112,7 @@ namespace OpenSim.Region.Framework.Scenes
111 protected ModuleLoader m_moduleLoader; 112 protected ModuleLoader m_moduleLoader;
112 protected AgentCircuitManager m_authenticateHandler; 113 protected AgentCircuitManager m_authenticateHandler;
113 protected SceneCommunicationService m_sceneGridService; 114 protected SceneCommunicationService m_sceneGridService;
115 protected ISnmpModule m_snmpService = null;
114 116
115 protected ISimulationDataService m_SimulationDataService; 117 protected ISimulationDataService m_SimulationDataService;
116 protected IEstateDataService m_EstateDataService; 118 protected IEstateDataService m_EstateDataService;
@@ -167,7 +169,7 @@ namespace OpenSim.Region.Framework.Scenes
167 private int m_update_events = 1; 169 private int m_update_events = 1;
168 private int m_update_backup = 200; 170 private int m_update_backup = 200;
169 private int m_update_terrain = 50; 171 private int m_update_terrain = 50;
170// private int m_update_land = 1; 172 private int m_update_land = 10;
171 private int m_update_coarse_locations = 50; 173 private int m_update_coarse_locations = 50;
172 174
173 private int frameMS; 175 private int frameMS;
@@ -181,6 +183,7 @@ namespace OpenSim.Region.Framework.Scenes
181 private int landMS; 183 private int landMS;
182 private int lastCompletedFrame; 184 private int lastCompletedFrame;
183 185
186 public bool CombineRegions = false;
184 private bool m_physics_enabled = true; 187 private bool m_physics_enabled = true;
185 private bool m_scripts_enabled = true; 188 private bool m_scripts_enabled = true;
186 private string m_defaultScriptEngine; 189 private string m_defaultScriptEngine;
@@ -189,6 +192,8 @@ namespace OpenSim.Region.Framework.Scenes
189 private volatile bool shuttingdown; 192 private volatile bool shuttingdown;
190 193
191 private int m_lastUpdate; 194 private int m_lastUpdate;
195 private int m_lastIncoming;
196 private int m_lastOutgoing;
192 private bool m_firstHeartbeat = true; 197 private bool m_firstHeartbeat = true;
193 198
194 private object m_deleting_scene_object = new object(); 199 private object m_deleting_scene_object = new object();
@@ -240,6 +245,19 @@ namespace OpenSim.Region.Framework.Scenes
240 get { return m_sceneGridService; } 245 get { return m_sceneGridService; }
241 } 246 }
242 247
248 public ISnmpModule SnmpService
249 {
250 get
251 {
252 if (m_snmpService == null)
253 {
254 m_snmpService = RequestModuleInterface<ISnmpModule>();
255 }
256
257 return m_snmpService;
258 }
259 }
260
243 public ISimulationDataService SimulationDataService 261 public ISimulationDataService SimulationDataService
244 { 262 {
245 get 263 get
@@ -563,7 +581,10 @@ namespace OpenSim.Region.Framework.Scenes
563 m_regInfo = regInfo; 581 m_regInfo = regInfo;
564 m_regionHandle = m_regInfo.RegionHandle; 582 m_regionHandle = m_regInfo.RegionHandle;
565 m_regionName = m_regInfo.RegionName; 583 m_regionName = m_regInfo.RegionName;
584 m_datastore = m_regInfo.DataStore;
566 m_lastUpdate = Util.EnvironmentTickCount(); 585 m_lastUpdate = Util.EnvironmentTickCount();
586 m_lastIncoming = 0;
587 m_lastOutgoing = 0;
567 588
568 m_physicalPrim = physicalPrim; 589 m_physicalPrim = physicalPrim;
569 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor; 590 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
@@ -577,6 +598,8 @@ namespace OpenSim.Region.Framework.Scenes
577 #region Region Settings 598 #region Region Settings
578 599
579 // Load region settings 600 // Load region settings
601 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID);
602
580 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID); 603 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
581 if (estateDataService != null) 604 if (estateDataService != null)
582 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 605 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -638,9 +661,10 @@ namespace OpenSim.Region.Framework.Scenes
638 //Animation states 661 //Animation states
639 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 662 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
640 // TODO: Change default to true once the feature is supported 663 // TODO: Change default to true once the feature is supported
641 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 664 m_usePreJump = startupConfig.GetBoolean("enableprejump", true);
642
643 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 665 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
666
667 m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF");
644 if (RegionInfo.NonphysPrimMax > 0) 668 if (RegionInfo.NonphysPrimMax > 0)
645 { 669 {
646 m_maxNonphys = RegionInfo.NonphysPrimMax; 670 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -672,6 +696,7 @@ namespace OpenSim.Region.Framework.Scenes
672 m_persistAfter *= 10000000; 696 m_persistAfter *= 10000000;
673 697
674 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 698 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
699 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
675 700
676 IConfig packetConfig = m_config.Configs["PacketPool"]; 701 IConfig packetConfig = m_config.Configs["PacketPool"];
677 if (packetConfig != null) 702 if (packetConfig != null)
@@ -681,6 +706,8 @@ namespace OpenSim.Region.Framework.Scenes
681 } 706 }
682 707
683 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 708 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
709 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
710 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
684 711
685 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 712 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
686 if (m_generateMaptiles) 713 if (m_generateMaptiles)
@@ -705,9 +732,9 @@ namespace OpenSim.Region.Framework.Scenes
705 } 732 }
706 } 733 }
707 } 734 }
708 catch 735 catch (Exception e)
709 { 736 {
710 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 737 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
711 } 738 }
712 739
713 #endregion Region Config 740 #endregion Region Config
@@ -1078,7 +1105,9 @@ namespace OpenSim.Region.Framework.Scenes
1078 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1105 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1079 if (HeartbeatThread != null) 1106 if (HeartbeatThread != null)
1080 { 1107 {
1108 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1081 HeartbeatThread.Abort(); 1109 HeartbeatThread.Abort();
1110 Watchdog.RemoveThread(HeartbeatThread.ManagedThreadId);
1082 HeartbeatThread = null; 1111 HeartbeatThread = null;
1083 } 1112 }
1084 m_lastUpdate = Util.EnvironmentTickCount(); 1113 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1202,9 +1231,6 @@ namespace OpenSim.Region.Framework.Scenes
1202 { 1231 {
1203 while (!shuttingdown) 1232 while (!shuttingdown)
1204 Update(); 1233 Update();
1205
1206 m_lastUpdate = Util.EnvironmentTickCount();
1207 m_firstHeartbeat = false;
1208 } 1234 }
1209 catch (ThreadAbortException) 1235 catch (ThreadAbortException)
1210 { 1236 {
@@ -1310,12 +1336,12 @@ namespace OpenSim.Region.Framework.Scenes
1310 terrainMS = Util.EnvironmentTickCountSubtract(terMS); 1336 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1311 } 1337 }
1312 1338
1313 //if (Frame % m_update_land == 0) 1339 // if (Frame % m_update_land == 0)
1314 //{ 1340 // {
1315 // int ldMS = Util.EnvironmentTickCount(); 1341 // int ldMS = Util.EnvironmentTickCount();
1316 // UpdateLand(); 1342 // UpdateLand();
1317 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1343 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1318 //} 1344 // }
1319 1345
1320 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); 1346 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
1321 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1347 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
@@ -1381,12 +1407,16 @@ namespace OpenSim.Region.Framework.Scenes
1381 maintc = Util.EnvironmentTickCountSubtract(maintc); 1407 maintc = Util.EnvironmentTickCountSubtract(maintc);
1382 maintc = (int)(m_timespan * 1000) - maintc; 1408 maintc = (int)(m_timespan * 1000) - maintc;
1383 1409
1410
1411 m_lastUpdate = Util.EnvironmentTickCount();
1412 m_firstHeartbeat = false;
1413
1384 if (maintc > 0) 1414 if (maintc > 0)
1385 Thread.Sleep(maintc); 1415 Thread.Sleep(maintc);
1386 1416
1387 // Tell the watchdog that this thread is still alive 1417 // Tell the watchdog that this thread is still alive
1388 Watchdog.UpdateThread(); 1418 Watchdog.UpdateThread();
1389 } 1419 }
1390 1420
1391 public void AddGroupTarget(SceneObjectGroup grp) 1421 public void AddGroupTarget(SceneObjectGroup grp)
1392 { 1422 {
@@ -1402,9 +1432,9 @@ namespace OpenSim.Region.Framework.Scenes
1402 1432
1403 private void CheckAtTargets() 1433 private void CheckAtTargets()
1404 { 1434 {
1405 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1435 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1406 lock (m_groupsWithTargets) 1436 lock (m_groupsWithTargets)
1407 objs = m_groupsWithTargets.Values; 1437 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1408 1438
1409 foreach (SceneObjectGroup entry in objs) 1439 foreach (SceneObjectGroup entry in objs)
1410 entry.checkAtTargets(); 1440 entry.checkAtTargets();
@@ -1727,14 +1757,24 @@ namespace OpenSim.Region.Framework.Scenes
1727 /// <returns></returns> 1757 /// <returns></returns>
1728 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1758 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1729 { 1759 {
1760
1761 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1762 Vector3 wpos = Vector3.Zero;
1763 // Check for water surface intersection from above
1764 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1765 {
1766 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1767 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1768 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1769 wpos.Z = wheight;
1770 }
1771
1730 Vector3 pos = Vector3.Zero; 1772 Vector3 pos = Vector3.Zero;
1731 if (RayEndIsIntersection == (byte)1) 1773 if (RayEndIsIntersection == (byte)1)
1732 { 1774 {
1733 pos = RayEnd; 1775 pos = RayEnd;
1734 return pos;
1735 } 1776 }
1736 1777 else if (RayTargetID != UUID.Zero)
1737 if (RayTargetID != UUID.Zero)
1738 { 1778 {
1739 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1779 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1740 1780
@@ -1756,7 +1796,7 @@ namespace OpenSim.Region.Framework.Scenes
1756 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1796 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1757 1797
1758 // Un-comment out the following line to Get Raytrace results printed to the console. 1798 // Un-comment out the following line to Get Raytrace results printed to the console.
1759 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1799 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1760 float ScaleOffset = 0.5f; 1800 float ScaleOffset = 0.5f;
1761 1801
1762 // If we hit something 1802 // If we hit something
@@ -1779,13 +1819,10 @@ namespace OpenSim.Region.Framework.Scenes
1779 //pos.Z -= 0.25F; 1819 //pos.Z -= 0.25F;
1780 1820
1781 } 1821 }
1782
1783 return pos;
1784 } 1822 }
1785 else 1823 else
1786 { 1824 {
1787 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1825 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1788
1789 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1826 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1790 1827
1791 // Un-comment the following line to print the raytrace results to the console. 1828 // Un-comment the following line to print the raytrace results to the console.
@@ -1794,13 +1831,12 @@ namespace OpenSim.Region.Framework.Scenes
1794 if (ei.HitTF) 1831 if (ei.HitTF)
1795 { 1832 {
1796 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1833 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1797 } else 1834 }
1835 else
1798 { 1836 {
1799 // fall back to our stupid functionality 1837 // fall back to our stupid functionality
1800 pos = RayEnd; 1838 pos = RayEnd;
1801 } 1839 }
1802
1803 return pos;
1804 } 1840 }
1805 } 1841 }
1806 else 1842 else
@@ -1811,8 +1847,12 @@ namespace OpenSim.Region.Framework.Scenes
1811 //increase height so its above the ground. 1847 //increase height so its above the ground.
1812 //should be getting the normal of the ground at the rez point and using that? 1848 //should be getting the normal of the ground at the rez point and using that?
1813 pos.Z += scale.Z / 2f; 1849 pos.Z += scale.Z / 2f;
1814 return pos; 1850// return pos;
1815 } 1851 }
1852
1853 // check against posible water intercept
1854 if (wpos.Z > pos.Z) pos = wpos;
1855 return pos;
1816 } 1856 }
1817 1857
1818 1858
@@ -1892,7 +1932,10 @@ namespace OpenSim.Region.Framework.Scenes
1892 public bool AddRestoredSceneObject( 1932 public bool AddRestoredSceneObject(
1893 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1933 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1894 { 1934 {
1895 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1935 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1936 if (result)
1937 sceneObject.IsDeleted = false;
1938 return result;
1896 } 1939 }
1897 1940
1898 /// <summary> 1941 /// <summary>
@@ -1981,6 +2024,15 @@ namespace OpenSim.Region.Framework.Scenes
1981 /// </summary> 2024 /// </summary>
1982 public void DeleteAllSceneObjects() 2025 public void DeleteAllSceneObjects()
1983 { 2026 {
2027 DeleteAllSceneObjects(false);
2028 }
2029
2030 /// <summary>
2031 /// Delete every object from the scene. This does not include attachments worn by avatars.
2032 /// </summary>
2033 public void DeleteAllSceneObjects(bool exceptNoCopy)
2034 {
2035 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
1984 lock (Entities) 2036 lock (Entities)
1985 { 2037 {
1986 EntityBase[] entities = Entities.GetEntities(); 2038 EntityBase[] entities = Entities.GetEntities();
@@ -1989,11 +2041,24 @@ namespace OpenSim.Region.Framework.Scenes
1989 if (e is SceneObjectGroup) 2041 if (e is SceneObjectGroup)
1990 { 2042 {
1991 SceneObjectGroup sog = (SceneObjectGroup)e; 2043 SceneObjectGroup sog = (SceneObjectGroup)e;
1992 if (!sog.IsAttachment) 2044 if (sog != null && !sog.IsAttachment)
1993 DeleteSceneObject((SceneObjectGroup)e, false); 2045 {
2046 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2047 {
2048 DeleteSceneObject((SceneObjectGroup)e, false);
2049 }
2050 else
2051 {
2052 toReturn.Add((SceneObjectGroup)e);
2053 }
2054 }
1994 } 2055 }
1995 } 2056 }
1996 } 2057 }
2058 if (toReturn.Count > 0)
2059 {
2060 returnObjects(toReturn.ToArray(), UUID.Zero);
2061 }
1997 } 2062 }
1998 2063
1999 /// <summary> 2064 /// <summary>
@@ -2042,6 +2107,8 @@ namespace OpenSim.Region.Framework.Scenes
2042 } 2107 }
2043 2108
2044 group.DeleteGroupFromScene(silent); 2109 group.DeleteGroupFromScene(silent);
2110 if (!silent)
2111 SendKillObject(new List<uint>() { group.LocalId });
2045 2112
2046// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2113// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2047 } 2114 }
@@ -2378,10 +2445,17 @@ namespace OpenSim.Region.Framework.Scenes
2378 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2445 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2379 public bool AddSceneObject(SceneObjectGroup sceneObject) 2446 public bool AddSceneObject(SceneObjectGroup sceneObject)
2380 { 2447 {
2448 if (sceneObject.OwnerID == UUID.Zero)
2449 {
2450 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2451 return false;
2452 }
2453
2381 // If the user is banned, we won't let any of their objects 2454 // If the user is banned, we won't let any of their objects
2382 // enter. Period. 2455 // enter. Period.
2383 // 2456 //
2384 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2457 int flags = GetUserFlags(sceneObject.OwnerID);
2458 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2385 { 2459 {
2386 m_log.Info("[INTERREGION]: Denied prim crossing for " + 2460 m_log.Info("[INTERREGION]: Denied prim crossing for " +
2387 "banned avatar"); 2461 "banned avatar");
@@ -2425,15 +2499,28 @@ namespace OpenSim.Region.Framework.Scenes
2425 2499
2426 if (AttachmentsModule != null) 2500 if (AttachmentsModule != null)
2427 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2501 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2502
2503 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2428 } 2504 }
2429 else 2505 else
2430 { 2506 {
2507 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2431 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2508 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2432 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2509 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2433 } 2510 }
2511 if (sceneObject.OwnerID == UUID.Zero)
2512 {
2513 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2514 return false;
2515 }
2434 } 2516 }
2435 else 2517 else
2436 { 2518 {
2519 if (sceneObject.OwnerID == UUID.Zero)
2520 {
2521 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2522 return false;
2523 }
2437 AddRestoredSceneObject(sceneObject, true, false); 2524 AddRestoredSceneObject(sceneObject, true, false);
2438 2525
2439 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2526 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2463,6 +2550,24 @@ namespace OpenSim.Region.Framework.Scenes
2463 return 2; // StateSource.PrimCrossing 2550 return 2; // StateSource.PrimCrossing
2464 } 2551 }
2465 2552
2553 public int GetUserFlags(UUID user)
2554 {
2555 //Unfortunately the SP approach means that the value is cached until region is restarted
2556 /*
2557 ScenePresence sp;
2558 if (TryGetScenePresence(user, out sp))
2559 {
2560 return sp.UserFlags;
2561 }
2562 else
2563 {
2564 */
2565 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2566 if (uac == null)
2567 return 0;
2568 return uac.UserFlags;
2569 //}
2570 }
2466 #endregion 2571 #endregion
2467 2572
2468 #region Add/Remove Avatar Methods 2573 #region Add/Remove Avatar Methods
@@ -2483,6 +2588,7 @@ namespace OpenSim.Region.Framework.Scenes
2483 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2588 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2484 2589
2485 CheckHeartbeat(); 2590 CheckHeartbeat();
2591 ScenePresence presence;
2486 2592
2487 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here 2593 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here
2488 { 2594 {
@@ -2506,12 +2612,19 @@ namespace OpenSim.Region.Framework.Scenes
2506 } 2612 }
2507 } 2613 }
2508 2614
2509 if (GetScenePresence(client.AgentId) != null) 2615 if (TryGetScenePresence(client.AgentId, out presence))
2510 { 2616 {
2511 m_LastLogin = Util.EnvironmentTickCount(); 2617 m_LastLogin = Util.EnvironmentTickCount();
2512 EventManager.TriggerOnNewClient(client); 2618 EventManager.TriggerOnNewClient(client);
2513 if (vialogin) 2619 if (vialogin)
2620 {
2514 EventManager.TriggerOnClientLogin(client); 2621 EventManager.TriggerOnClientLogin(client);
2622
2623 // Send initial parcel data
2624 Vector3 pos = presence.AbsolutePosition;
2625 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2626 land.SendLandUpdateToClient(presence.ControllingClient);
2627 }
2515 } 2628 }
2516 } 2629 }
2517 2630
@@ -2562,19 +2675,12 @@ namespace OpenSim.Region.Framework.Scenes
2562 // and the scene presence and the client, if they exist 2675 // and the scene presence and the client, if they exist
2563 try 2676 try
2564 { 2677 {
2565 // We need to wait for the client to make UDP contact first. 2678 ScenePresence sp = GetScenePresence(agentID);
2566 // It's the UDP contact that creates the scene presence 2679 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2567 ScenePresence sp = WaitGetScenePresence(agentID); 2680
2568 if (sp != null) 2681 if (sp != null)
2569 {
2570 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2571
2572 sp.ControllingClient.Close(); 2682 sp.ControllingClient.Close();
2573 } 2683
2574 else
2575 {
2576 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2577 }
2578 // BANG! SLASH! 2684 // BANG! SLASH!
2579 m_authenticateHandler.RemoveCircuit(agentID); 2685 m_authenticateHandler.RemoveCircuit(agentID);
2580 2686
@@ -2674,6 +2780,7 @@ namespace OpenSim.Region.Framework.Scenes
2674 client.OnFetchInventory += HandleFetchInventory; 2780 client.OnFetchInventory += HandleFetchInventory;
2675 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2781 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2676 client.OnCopyInventoryItem += CopyInventoryItem; 2782 client.OnCopyInventoryItem += CopyInventoryItem;
2783 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2677 client.OnMoveInventoryItem += MoveInventoryItem; 2784 client.OnMoveInventoryItem += MoveInventoryItem;
2678 client.OnRemoveInventoryItem += RemoveInventoryItem; 2785 client.OnRemoveInventoryItem += RemoveInventoryItem;
2679 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2786 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2852,15 +2959,16 @@ namespace OpenSim.Region.Framework.Scenes
2852 /// </summary> 2959 /// </summary>
2853 /// <param name="agentId">The avatar's Unique ID</param> 2960 /// <param name="agentId">The avatar's Unique ID</param>
2854 /// <param name="client">The IClientAPI for the client</param> 2961 /// <param name="client">The IClientAPI for the client</param>
2855 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 2962 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2856 { 2963 {
2857 if (m_teleportModule != null) 2964 if (m_teleportModule != null)
2858 m_teleportModule.TeleportHome(agentId, client); 2965 return m_teleportModule.TeleportHome(agentId, client);
2859 else 2966 else
2860 { 2967 {
2861 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 2968 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2862 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 2969 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2863 } 2970 }
2971 return false;
2864 } 2972 }
2865 2973
2866 /// <summary> 2974 /// <summary>
@@ -2959,6 +3067,16 @@ namespace OpenSim.Region.Framework.Scenes
2959 /// <param name="flags"></param> 3067 /// <param name="flags"></param>
2960 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3068 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
2961 { 3069 {
3070 //Add half the avatar's height so that the user doesn't fall through prims
3071 ScenePresence presence;
3072 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3073 {
3074 if (presence.Appearance != null)
3075 {
3076 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3077 }
3078 }
3079
2962 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3080 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
2963 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3081 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
2964 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3082 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3035,7 +3153,9 @@ namespace OpenSim.Region.Framework.Scenes
3035 regions.Remove(RegionInfo.RegionHandle); 3153 regions.Remove(RegionInfo.RegionHandle);
3036 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3154 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3037 } 3155 }
3156 m_log.Debug("[Scene] Beginning ClientClosed");
3038 m_eventManager.TriggerClientClosed(agentID, this); 3157 m_eventManager.TriggerClientClosed(agentID, this);
3158 m_log.Debug("[Scene] Finished ClientClosed");
3039 } 3159 }
3040 catch (NullReferenceException) 3160 catch (NullReferenceException)
3041 { 3161 {
@@ -3043,7 +3163,12 @@ namespace OpenSim.Region.Framework.Scenes
3043 // Avatar is already disposed :/ 3163 // Avatar is already disposed :/
3044 } 3164 }
3045 3165
3166 m_log.Debug("[Scene] Beginning OnRemovePresence");
3046 m_eventManager.TriggerOnRemovePresence(agentID); 3167 m_eventManager.TriggerOnRemovePresence(agentID);
3168 m_log.Debug("[Scene] Finished OnRemovePresence");
3169
3170 if (avatar != null && (!avatar.IsChildAgent))
3171 avatar.SaveChangedAttachments();
3047 3172
3048 if (avatar != null && (!avatar.IsChildAgent)) 3173 if (avatar != null && (!avatar.IsChildAgent))
3049 avatar.SaveChangedAttachments(); 3174 avatar.SaveChangedAttachments();
@@ -3052,7 +3177,7 @@ namespace OpenSim.Region.Framework.Scenes
3052 delegate(IClientAPI client) 3177 delegate(IClientAPI client)
3053 { 3178 {
3054 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3179 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3055 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3180 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3056 catch (NullReferenceException) { } 3181 catch (NullReferenceException) { }
3057 }); 3182 });
3058 3183
@@ -3063,8 +3188,11 @@ namespace OpenSim.Region.Framework.Scenes
3063 } 3188 }
3064 3189
3065 // Remove the avatar from the scene 3190 // Remove the avatar from the scene
3191 m_log.Debug("[Scene] Begin RemoveScenePresence");
3066 m_sceneGraph.RemoveScenePresence(agentID); 3192 m_sceneGraph.RemoveScenePresence(agentID);
3193 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3067 m_clientManager.Remove(agentID); 3194 m_clientManager.Remove(agentID);
3195 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3068 3196
3069 try 3197 try
3070 { 3198 {
@@ -3078,9 +3206,10 @@ namespace OpenSim.Region.Framework.Scenes
3078 { 3206 {
3079 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3207 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3080 } 3208 }
3081 3209 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3082 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3210 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3083 CleanDroppedAttachments(); 3211 CleanDroppedAttachments();
3212 m_log.Debug("[Scene] The avatar has left the building");
3084 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3213 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3085 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3214 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3086 } 3215 }
@@ -3111,18 +3240,24 @@ namespace OpenSim.Region.Framework.Scenes
3111 3240
3112 #region Entities 3241 #region Entities
3113 3242
3114 public void SendKillObject(uint localID) 3243 public void SendKillObject(List<uint> localIDs)
3115 { 3244 {
3116 SceneObjectPart part = GetSceneObjectPart(localID); 3245 List<uint> deleteIDs = new List<uint>();
3117 if (part != null) // It is a prim 3246
3247 foreach (uint localID in localIDs)
3118 { 3248 {
3119 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3249 SceneObjectPart part = GetSceneObjectPart(localID);
3250 if (part != null) // It is a prim
3120 { 3251 {
3121 if (part.ParentGroup.RootPart != part) // Child part 3252 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3122 return; 3253 {
3254 if (part.ParentGroup.RootPart != part) // Child part
3255 continue;
3256 }
3123 } 3257 }
3258 deleteIDs.Add(localID);
3124 } 3259 }
3125 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); 3260 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3126 } 3261 }
3127 3262
3128 #endregion 3263 #endregion
@@ -3140,7 +3275,6 @@ namespace OpenSim.Region.Framework.Scenes
3140 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3275 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3141 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3276 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3142 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3277 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3143 m_sceneGridService.KiPrimitive += SendKillObject;
3144 m_sceneGridService.OnGetLandData += GetLandData; 3278 m_sceneGridService.OnGetLandData += GetLandData;
3145 } 3279 }
3146 3280
@@ -3149,7 +3283,6 @@ namespace OpenSim.Region.Framework.Scenes
3149 /// </summary> 3283 /// </summary>
3150 public void UnRegisterRegionWithComms() 3284 public void UnRegisterRegionWithComms()
3151 { 3285 {
3152 m_sceneGridService.KiPrimitive -= SendKillObject;
3153 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3286 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3154 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3287 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3155 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3288 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3229,13 +3362,16 @@ namespace OpenSim.Region.Framework.Scenes
3229 sp = null; 3362 sp = null;
3230 } 3363 }
3231 3364
3232 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3233 3365
3234 //On login test land permisions 3366 //On login test land permisions
3235 if (vialogin) 3367 if (vialogin)
3236 { 3368 {
3237 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3369 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3370 if (cache != null)
3371 cache.Remove(agent.firstname + " " + agent.lastname);
3372 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3238 { 3373 {
3374 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3239 return false; 3375 return false;
3240 } 3376 }
3241 } 3377 }
@@ -3258,8 +3394,13 @@ namespace OpenSim.Region.Framework.Scenes
3258 3394
3259 try 3395 try
3260 { 3396 {
3261 if (!AuthorizeUser(agent, out reason)) 3397 // Always check estate if this is a login. Always
3262 return false; 3398 // check if banned regions are to be blacked out.
3399 if (vialogin || (!m_seeIntoBannedRegion))
3400 {
3401 if (!AuthorizeUser(agent.AgentID, out reason))
3402 return false;
3403 }
3263 } 3404 }
3264 catch (Exception e) 3405 catch (Exception e)
3265 { 3406 {
@@ -3362,6 +3503,8 @@ namespace OpenSim.Region.Framework.Scenes
3362 } 3503 }
3363 } 3504 }
3364 // Honor parcel landing type and position. 3505 // Honor parcel landing type and position.
3506 /*
3507 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3365 if (land != null) 3508 if (land != null)
3366 { 3509 {
3367 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3510 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3369,26 +3512,34 @@ namespace OpenSim.Region.Framework.Scenes
3369 agent.startpos = land.LandData.UserLocation; 3512 agent.startpos = land.LandData.UserLocation;
3370 } 3513 }
3371 } 3514 }
3515 */// This is now handled properly in ScenePresence.MakeRootAgent
3372 } 3516 }
3373 3517
3374 return true; 3518 return true;
3375 } 3519 }
3376 3520
3377 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3521 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3378 { 3522 {
3379 3523 reason = String.Empty;
3380 bool banned = land.IsBannedFromLand(agent.AgentID); 3524 if (Permissions.IsGod(agentID))
3381 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3525 return true;
3526
3527 ILandObject land = LandChannel.GetLandObject(posX, posY);
3528 if (land == null)
3529 return false;
3530
3531 bool banned = land.IsBannedFromLand(agentID);
3532 bool restricted = land.IsRestrictedFromLand(agentID);
3382 3533
3383 if (banned || restricted) 3534 if (banned || restricted)
3384 { 3535 {
3385 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3536 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3386 if (nearestParcel != null) 3537 if (nearestParcel != null)
3387 { 3538 {
3388 //Move agent to nearest allowed 3539 //Move agent to nearest allowed
3389 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3540 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3390 agent.startpos.X = newPosition.X; 3541 posX = newPosition.X;
3391 agent.startpos.Y = newPosition.Y; 3542 posY = newPosition.Y;
3392 } 3543 }
3393 else 3544 else
3394 { 3545 {
@@ -3444,19 +3595,19 @@ namespace OpenSim.Region.Framework.Scenes
3444 /// <param name="reason">outputs the reason to this string</param> 3595 /// <param name="reason">outputs the reason to this string</param>
3445 /// <returns>True if the region accepts this agent. False if it does not. False will 3596 /// <returns>True if the region accepts this agent. False if it does not. False will
3446 /// also return a reason.</returns> 3597 /// also return a reason.</returns>
3447 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 3598 protected virtual bool AuthorizeUser(UUID agentID, out string reason)
3448 { 3599 {
3449 reason = String.Empty; 3600 reason = String.Empty;
3450 3601
3451 if (!m_strictAccessControl) return true; 3602 if (!m_strictAccessControl) return true;
3452 if (Permissions.IsGod(agent.AgentID)) return true; 3603 if (Permissions.IsGod(agentID)) return true;
3453 3604
3454 if (AuthorizationService != null) 3605 if (AuthorizationService != null)
3455 { 3606 {
3456 if (!AuthorizationService.IsAuthorizedForRegion(agent.AgentID.ToString(), RegionInfo.RegionID.ToString(),out reason)) 3607 if (!AuthorizationService.IsAuthorizedForRegion(agentID.ToString(), RegionInfo.RegionID.ToString(),out reason))
3457 { 3608 {
3458 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3609 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the region",
3459 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3610 agentID, RegionInfo.RegionName);
3460 //reason = String.Format("You are not currently on the access list for {0}",RegionInfo.RegionName); 3611 //reason = String.Format("You are not currently on the access list for {0}",RegionInfo.RegionName);
3461 return false; 3612 return false;
3462 } 3613 }
@@ -3464,10 +3615,26 @@ namespace OpenSim.Region.Framework.Scenes
3464 3615
3465 if (m_regInfo.EstateSettings != null) 3616 if (m_regInfo.EstateSettings != null)
3466 { 3617 {
3467 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3618 int flags = GetUserFlags(agentID);
3619 if (m_regInfo.EstateSettings.IsBanned(agentID, flags))
3468 { 3620 {
3469 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3621 //Add some more info to help users
3470 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3622 if (!m_regInfo.EstateSettings.IsBanned(agentID, 32))
3623 {
3624 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the region requires age verification",
3625 agentID, RegionInfo.RegionName);
3626 reason = String.Format("Denied access to region {0}: Region requires age verification", RegionInfo.RegionName);
3627 return false;
3628 }
3629 if (!m_regInfo.EstateSettings.IsBanned(agentID, 4))
3630 {
3631 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} {1} because the region requires payment info on file",
3632 agentID, RegionInfo.RegionName);
3633 reason = String.Format("Denied access to region {0}: Region requires payment info on file", RegionInfo.RegionName);
3634 return false;
3635 }
3636 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {3} because the user is on the banlist",
3637 agentID, RegionInfo.RegionName);
3471 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 3638 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
3472 RegionInfo.RegionName); 3639 RegionInfo.RegionName);
3473 return false; 3640 return false;
@@ -3484,7 +3651,7 @@ namespace OpenSim.Region.Framework.Scenes
3484 if (groupsModule != null) 3651 if (groupsModule != null)
3485 { 3652 {
3486 GroupMembershipData[] GroupMembership = 3653 GroupMembershipData[] GroupMembership =
3487 groupsModule.GetMembershipData(agent.AgentID); 3654 groupsModule.GetMembershipData(agentID);
3488 3655
3489 if (GroupMembership != null) 3656 if (GroupMembership != null)
3490 { 3657 {
@@ -3513,44 +3680,16 @@ namespace OpenSim.Region.Framework.Scenes
3513 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 3680 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
3514 3681
3515 if (!m_regInfo.EstateSettings.PublicAccess && 3682 if (!m_regInfo.EstateSettings.PublicAccess &&
3516 !m_regInfo.EstateSettings.HasAccess(agent.AgentID) && 3683 !m_regInfo.EstateSettings.HasAccess(agentID) &&
3517 !groupAccess) 3684 !groupAccess)
3518 { 3685 {
3519 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 3686 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the estate",
3520 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3687 agentID, RegionInfo.RegionName);
3521 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 3688 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3522 RegionInfo.RegionName); 3689 RegionInfo.RegionName);
3523 return false; 3690 return false;
3524 } 3691 }
3525 3692
3526 // TODO: estate/region settings are not properly hooked up
3527 // to ILandObject.isRestrictedFromLand()
3528 // if (null != LandChannel)
3529 // {
3530 // // region seems to have local Id of 1
3531 // ILandObject land = LandChannel.GetLandObject(1);
3532 // if (null != land)
3533 // {
3534 // if (land.isBannedFromLand(agent.AgentID))
3535 // {
3536 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land",
3537 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3538 // reason = String.Format("Denied access to private region {0}: You are banned from that region.",
3539 // RegionInfo.RegionName);
3540 // return false;
3541 // }
3542
3543 // if (land.isRestrictedFromLand(agent.AgentID))
3544 // {
3545 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3546 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3547 // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3548 // RegionInfo.RegionName);
3549 // return false;
3550 // }
3551 // }
3552 // }
3553
3554 return true; 3693 return true;
3555 } 3694 }
3556 3695
@@ -3654,6 +3793,13 @@ namespace OpenSim.Region.Framework.Scenes
3654 3793
3655 // We have to wait until the viewer contacts this region after receiving EAC. 3794 // We have to wait until the viewer contacts this region after receiving EAC.
3656 // That calls AddNewClient, which finally creates the ScenePresence 3795 // That calls AddNewClient, which finally creates the ScenePresence
3796 int flags = GetUserFlags(cAgentData.AgentID);
3797 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3798 {
3799 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3800 return false;
3801 }
3802
3657 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3803 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3658 if (nearestParcel == null) 3804 if (nearestParcel == null)
3659 { 3805 {
@@ -3669,7 +3815,6 @@ namespace OpenSim.Region.Framework.Scenes
3669 return false; 3815 return false;
3670 } 3816 }
3671 3817
3672
3673 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3818 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3674 3819
3675 if (childAgentUpdate != null) 3820 if (childAgentUpdate != null)
@@ -3736,12 +3881,22 @@ namespace OpenSim.Region.Framework.Scenes
3736 return false; 3881 return false;
3737 } 3882 }
3738 3883
3884 public bool IncomingCloseAgent(UUID agentID)
3885 {
3886 return IncomingCloseAgent(agentID, false);
3887 }
3888
3889 public bool IncomingCloseChildAgent(UUID agentID)
3890 {
3891 return IncomingCloseAgent(agentID, true);
3892 }
3893
3739 /// <summary> 3894 /// <summary>
3740 /// Tell a single agent to disconnect from the region. 3895 /// Tell a single agent to disconnect from the region.
3741 /// </summary> 3896 /// </summary>
3742 /// <param name="regionHandle"></param>
3743 /// <param name="agentID"></param> 3897 /// <param name="agentID"></param>
3744 public bool IncomingCloseAgent(UUID agentID) 3898 /// <param name="childOnly"></param>
3899 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3745 { 3900 {
3746 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3901 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3747 3902
@@ -3753,7 +3908,7 @@ namespace OpenSim.Region.Framework.Scenes
3753 { 3908 {
3754 m_sceneGraph.removeUserCount(false); 3909 m_sceneGraph.removeUserCount(false);
3755 } 3910 }
3756 else 3911 else if (!childOnly)
3757 { 3912 {
3758 m_sceneGraph.removeUserCount(true); 3913 m_sceneGraph.removeUserCount(true);
3759 } 3914 }
@@ -3769,9 +3924,12 @@ namespace OpenSim.Region.Framework.Scenes
3769 } 3924 }
3770 else 3925 else
3771 presence.ControllingClient.SendShutdownConnectionNotice(); 3926 presence.ControllingClient.SendShutdownConnectionNotice();
3927 presence.ControllingClient.Close(false);
3928 }
3929 else if (!childOnly)
3930 {
3931 presence.ControllingClient.Close(true);
3772 } 3932 }
3773
3774 presence.ControllingClient.Close();
3775 return true; 3933 return true;
3776 } 3934 }
3777 3935
@@ -4381,34 +4539,66 @@ namespace OpenSim.Region.Framework.Scenes
4381 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4539 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4382 } 4540 }
4383 4541
4384 public int GetHealth() 4542 public int GetHealth(out int flags, out string message)
4385 { 4543 {
4386 // Returns: 4544 // Returns:
4387 // 1 = sim is up and accepting http requests. The heartbeat has 4545 // 1 = sim is up and accepting http requests. The heartbeat has
4388 // stopped and the sim is probably locked up, but a remote 4546 // stopped and the sim is probably locked up, but a remote
4389 // admin restart may succeed 4547 // admin restart may succeed
4390 // 4548 //
4391 // 2 = Sim is up and the heartbeat is running. The sim is likely 4549 // 2 = Sim is up and the heartbeat is running. The sim is likely
4392 // usable for people within and logins _may_ work 4550 // usable for people within
4551 //
4552 // 3 = Sim is up and one packet thread is running. Sim is
4553 // unstable and will not accept new logins
4393 // 4554 //
4394 // 3 = We have seen a new user enter within the past 4 minutes 4555 // 4 = Sim is up and both packet threads are running. Sim is
4556 // likely usable
4557 //
4558 // 5 = We have seen a new user enter within the past 4 minutes
4395 // which can be seen as positive confirmation of sim health 4559 // which can be seen as positive confirmation of sim health
4396 // 4560 //
4561
4562 flags = 0;
4563 message = String.Empty;
4564
4565 CheckHeartbeat();
4566
4567 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4568 {
4569 // We're still starting
4570 // 0 means "in startup", it can't happen another way, since
4571 // to get here, we must be able to accept http connections
4572 return 0;
4573 }
4574
4397 int health=1; // Start at 1, means we're up 4575 int health=1; // Start at 1, means we're up
4398 4576
4399 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4577 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4578 {
4400 health+=1; 4579 health+=1;
4401 else 4580 flags |= 1;
4581 }
4582
4583 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4584 {
4585 health+=1;
4586 flags |= 2;
4587 }
4588
4589 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4590 {
4591 health+=1;
4592 flags |= 4;
4593 }
4594
4595 if (flags != 7)
4402 return health; 4596 return health;
4403 4597
4404 // A login in the last 4 mins? We can't be doing too badly 4598 // A login in the last 4 mins? We can't be doing too badly
4405 // 4599 //
4406 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4600 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4407 health++; 4601 health++;
4408 else
4409 return health;
4410
4411 CheckHeartbeat();
4412 4602
4413 return health; 4603 return health;
4414 } 4604 }
@@ -4601,7 +4791,7 @@ namespace OpenSim.Region.Framework.Scenes
4601 if (m_firstHeartbeat) 4791 if (m_firstHeartbeat)
4602 return; 4792 return;
4603 4793
4604 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4794 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 10000)
4605 StartTimer(); 4795 StartTimer();
4606 } 4796 }
4607 4797
@@ -4956,10 +5146,28 @@ namespace OpenSim.Region.Framework.Scenes
4956 }); 5146 });
4957 } 5147 }
4958 5148
4959 foreach (SceneObjectGroup grp in objectsToDelete) 5149 if (objectsToDelete.Count > 0)
4960 { 5150 {
4961 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); 5151 m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count);
4962 DeleteSceneObject(grp, true); 5152 foreach (SceneObjectGroup grp in objectsToDelete)
5153 {
5154 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5155 DeleteSceneObject(grp, true);
5156 }
5157 m_log.Debug("[SCENE]: Finished dropped attachment deletion");
5158 }
5159 }
5160
5161 public void ThreadAlive(int threadCode)
5162 {
5163 switch(threadCode)
5164 {
5165 case 1: // Incoming
5166 m_lastIncoming = Util.EnvironmentTickCount();
5167 break;
5168 case 2: // Incoming
5169 m_lastOutgoing = Util.EnvironmentTickCount();
5170 break;
4963 } 5171 }
4964 } 5172 }
4965 5173
@@ -4971,6 +5179,14 @@ namespace OpenSim.Region.Framework.Scenes
4971 // child agent creation, thereby emulating the SL behavior. 5179 // child agent creation, thereby emulating the SL behavior.
4972 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5180 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
4973 { 5181 {
5182 reason = "You are banned from the region";
5183
5184 if (Permissions.IsGod(agentID))
5185 {
5186 reason = String.Empty;
5187 return true;
5188 }
5189
4974 int num = m_sceneGraph.GetNumberOfScenePresences(); 5190 int num = m_sceneGraph.GetNumberOfScenePresences();
4975 5191
4976 if (num >= RegionInfo.RegionSettings.AgentLimit) 5192 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -4982,6 +5198,36 @@ namespace OpenSim.Region.Framework.Scenes
4982 } 5198 }
4983 } 5199 }
4984 5200
5201 if (!AuthorizeUser(agentID, out reason))
5202 {
5203 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5204 return false;
5205 }
5206
5207 if (position == Vector3.Zero) // Teleport
5208 {
5209 float posX = 128.0f;
5210 float posY = 128.0f;
5211
5212 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5213 {
5214 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5215 return false;
5216 }
5217 }
5218 else // Walking
5219 {
5220 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5221 if (land == null)
5222 return false;
5223
5224 bool banned = land.IsBannedFromLand(agentID);
5225 bool restricted = land.IsRestrictedFromLand(agentID);
5226
5227 if (banned || restricted)
5228 return false;
5229 }
5230
4985 reason = String.Empty; 5231 reason = String.Empty;
4986 return true; 5232 return true;
4987 } 5233 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index c4547f2..f343bc8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 837e655..19cb0c1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -44,8 +44,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
44 44
45namespace OpenSim.Region.Framework.Scenes 45namespace OpenSim.Region.Framework.Scenes
46{ 46{
47 public delegate void KiPrimitiveDelegate(uint localID);
48
49 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst); 47 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
50 48
51 /// <summary> 49 /// <summary>
@@ -113,8 +111,6 @@ namespace OpenSim.Region.Framework.Scenes
113// private LogOffUser handlerLogOffUser = null; 111// private LogOffUser handlerLogOffUser = null;
114// private GetLandData handlerGetLandData = null; // OnGetLandData 112// private GetLandData handlerGetLandData = null; // OnGetLandData
115 113
116 public KiPrimitiveDelegate KiPrimitive;
117
118 public SceneCommunicationService() 114 public SceneCommunicationService()
119 { 115 {
120 } 116 }
@@ -168,7 +164,7 @@ namespace OpenSim.Region.Framework.Scenes
168 164
169 if (neighbour != null) 165 if (neighbour != null)
170 { 166 {
171 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 167 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
172 m_scene.EventManager.TriggerOnRegionUp(neighbour); 168 m_scene.EventManager.TriggerOnRegionUp(neighbour);
173 } 169 }
174 else 170 else
@@ -183,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
183 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 179 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
184 180
185 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 181 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
186 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 182 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
187 foreach (GridRegion n in neighbours) 183 foreach (GridRegion n in neighbours)
188 { 184 {
189 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 185 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -259,46 +255,42 @@ namespace OpenSim.Region.Framework.Scenes
259 255
260 } 256 }
261 257
262 //public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle); 258 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
263 //private void SendCloseChildAgentCompleted(IAsyncResult iar)
264 //{
265 // SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
266 // icon.EndInvoke(iar);
267 //}
268 259
269 /// <summary> 260 /// <summary>
270 /// Closes a child agent on a given region 261 /// This Closes child agents on neighboring regions
262 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
271 /// </summary> 263 /// </summary>
272 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 264 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
273 { 265 {
274 266
275 m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); 267 //m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
276 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 268 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
277 269
278 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 270 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
279 uint x = 0, y = 0; 271 uint x = 0, y = 0;
280 Utils.LongToUInts(regionHandle, out x, out y); 272 Utils.LongToUInts(regionHandle, out x, out y);
281 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 273 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
282 m_scene.SimulationService.CloseAgent(destination, agentID); 274 m_scene.SimulationService.CloseChildAgent(destination, agentID);
275 }
276
277 private void SendCloseChildAgentCompleted(IAsyncResult iar)
278 {
279 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
280 icon.EndInvoke(iar);
283 } 281 }
284 282
285 /// <summary>
286 /// Closes a child agents in a collection of regions. Does so asynchronously
287 /// so that the caller doesn't wait.
288 /// </summary>
289 /// <param name="agentID"></param>
290 /// <param name="regionslst"></param>
291 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 283 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
292 { 284 {
293 Util.FireAndForget(delegate 285 foreach (ulong handle in regionslst)
294 { 286 {
295 foreach (ulong handle in regionslst) 287 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
296 { 288 d.BeginInvoke(agentID, handle,
297 SendCloseChildAgent(agentID, handle); 289 SendCloseChildAgentCompleted,
298 } 290 d);
299 }); 291 }
300 } 292 }
301 293
302 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 294 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
303 { 295 {
304 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 296 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index fc31b65..3d6057b 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
@@ -135,13 +144,18 @@ namespace OpenSim.Region.Framework.Scenes
135 144
136 protected internal void Close() 145 protected internal void Close()
137 { 146 {
138 lock (m_presenceLock) 147 m_scenePresencesLock.EnterWriteLock();
148 try
139 { 149 {
140 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 150 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
141 List<ScenePresence> newlist = new List<ScenePresence>(); 151 List<ScenePresence> newlist = new List<ScenePresence>();
142 m_scenePresenceMap = newmap; 152 m_scenePresenceMap = newmap;
143 m_scenePresenceArray = newlist; 153 m_scenePresenceArray = newlist;
144 } 154 }
155 finally
156 {
157 m_scenePresencesLock.ExitWriteLock();
158 }
145 159
146 lock (SceneObjectGroupsByFullID) 160 lock (SceneObjectGroupsByFullID)
147 SceneObjectGroupsByFullID.Clear(); 161 SceneObjectGroupsByFullID.Clear();
@@ -273,6 +287,33 @@ namespace OpenSim.Region.Framework.Scenes
273 protected internal bool AddRestoredSceneObject( 287 protected internal bool AddRestoredSceneObject(
274 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 288 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
275 { 289 {
290 if (!m_parentScene.CombineRegions)
291 {
292 // KF: Check for out-of-region, move inside and make static.
293 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
294 sceneObject.RootPart.GroupPosition.Y,
295 sceneObject.RootPart.GroupPosition.Z);
296 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 ||
297 npos.X > Constants.RegionSize ||
298 npos.Y > Constants.RegionSize))
299 {
300 if (npos.X < 0.0) npos.X = 1.0f;
301 if (npos.Y < 0.0) npos.Y = 1.0f;
302 if (npos.Z < 0.0) npos.Z = 0.0f;
303 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
304 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
305
306 foreach (SceneObjectPart part in sceneObject.Parts)
307 {
308 part.GroupPosition = npos;
309 }
310 sceneObject.RootPart.Velocity = Vector3.Zero;
311 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
312 sceneObject.RootPart.Acceleration = Vector3.Zero;
313 sceneObject.RootPart.Velocity = Vector3.Zero;
314 }
315 }
316
276 if (attachToBackup && (!alreadyPersisted)) 317 if (attachToBackup && (!alreadyPersisted))
277 { 318 {
278 sceneObject.ForceInventoryPersistence(); 319 sceneObject.ForceInventoryPersistence();
@@ -482,6 +523,30 @@ namespace OpenSim.Region.Framework.Scenes
482 m_updateList[obj.UUID] = obj; 523 m_updateList[obj.UUID] = obj;
483 } 524 }
484 525
526 public void FireAttachToBackup(SceneObjectGroup obj)
527 {
528 if (OnAttachToBackup != null)
529 {
530 OnAttachToBackup(obj);
531 }
532 }
533
534 public void FireDetachFromBackup(SceneObjectGroup obj)
535 {
536 if (OnDetachFromBackup != null)
537 {
538 OnDetachFromBackup(obj);
539 }
540 }
541
542 public void FireChangeBackup(SceneObjectGroup obj)
543 {
544 if (OnChangeBackup != null)
545 {
546 OnChangeBackup(obj);
547 }
548 }
549
485 /// <summary> 550 /// <summary>
486 /// Process all pending updates 551 /// Process all pending updates
487 /// </summary> 552 /// </summary>
@@ -617,7 +682,8 @@ namespace OpenSim.Region.Framework.Scenes
617 682
618 Entities[presence.UUID] = presence; 683 Entities[presence.UUID] = presence;
619 684
620 lock (m_presenceLock) 685 m_scenePresencesLock.EnterWriteLock();
686 try
621 { 687 {
622 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 688 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
623 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 689 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -641,6 +707,10 @@ namespace OpenSim.Region.Framework.Scenes
641 m_scenePresenceMap = newmap; 707 m_scenePresenceMap = newmap;
642 m_scenePresenceArray = newlist; 708 m_scenePresenceArray = newlist;
643 } 709 }
710 finally
711 {
712 m_scenePresencesLock.ExitWriteLock();
713 }
644 } 714 }
645 715
646 /// <summary> 716 /// <summary>
@@ -655,7 +725,8 @@ namespace OpenSim.Region.Framework.Scenes
655 agentID); 725 agentID);
656 } 726 }
657 727
658 lock (m_presenceLock) 728 m_scenePresencesLock.EnterWriteLock();
729 try
659 { 730 {
660 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 731 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
661 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 732 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -677,6 +748,10 @@ namespace OpenSim.Region.Framework.Scenes
677 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 748 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
678 } 749 }
679 } 750 }
751 finally
752 {
753 m_scenePresencesLock.ExitWriteLock();
754 }
680 } 755 }
681 756
682 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 757 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1314,8 +1389,13 @@ namespace OpenSim.Region.Framework.Scenes
1314 { 1389 {
1315 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1390 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1316 { 1391 {
1317 if (m_parentScene.AttachmentsModule != null) 1392 // Set the new attachment point data in the object
1318 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1393 byte attachmentPoint = group.GetAttachmentPoint();
1394 group.UpdateGroupPosition(pos);
1395 group.RootPart.IsAttachment = false;
1396 group.AbsolutePosition = group.RootPart.AttachedPos;
1397 group.SetAttachmentPoint(attachmentPoint);
1398 group.HasGroupChanged = true;
1319 } 1399 }
1320 else 1400 else
1321 { 1401 {
@@ -1559,10 +1639,13 @@ namespace OpenSim.Region.Framework.Scenes
1559 /// <param name="childPrims"></param> 1639 /// <param name="childPrims"></param>
1560 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1640 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1561 { 1641 {
1642 SceneObjectGroup parentGroup = root.ParentGroup;
1643 if (parentGroup == null) return;
1562 Monitor.Enter(m_updateLock); 1644 Monitor.Enter(m_updateLock);
1645
1563 try 1646 try
1564 { 1647 {
1565 SceneObjectGroup parentGroup = root.ParentGroup; 1648 parentGroup.areUpdatesSuspended = true;
1566 1649
1567 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1650 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1568 if (parentGroup != null) 1651 if (parentGroup != null)
@@ -1574,11 +1657,6 @@ namespace OpenSim.Region.Framework.Scenes
1574 1657
1575 if (child != null) 1658 if (child != null)
1576 { 1659 {
1577 // Make sure no child prim is set for sale
1578 // So that, on delink, no prims are unwittingly
1579 // left for sale and sold off
1580 child.RootPart.ObjectSaleType = 0;
1581 child.RootPart.SalePrice = 10;
1582 childGroups.Add(child); 1660 childGroups.Add(child);
1583 } 1661 }
1584 } 1662 }
@@ -1601,12 +1679,13 @@ namespace OpenSim.Region.Framework.Scenes
1601 // occur on link to invoke this elsewhere (such as object selection) 1679 // occur on link to invoke this elsewhere (such as object selection)
1602 parentGroup.RootPart.CreateSelected = true; 1680 parentGroup.RootPart.CreateSelected = true;
1603 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1681 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1604 parentGroup.HasGroupChanged = true;
1605 parentGroup.ScheduleGroupForFullUpdate();
1606
1607 } 1682 }
1608 finally 1683 finally
1609 { 1684 {
1685 parentGroup.areUpdatesSuspended = false;
1686 parentGroup.HasGroupChanged = true;
1687 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1688 parentGroup.ScheduleGroupForFullUpdate();
1610 Monitor.Exit(m_updateLock); 1689 Monitor.Exit(m_updateLock);
1611 } 1690 }
1612 } 1691 }
@@ -1638,21 +1717,24 @@ namespace OpenSim.Region.Framework.Scenes
1638 1717
1639 SceneObjectGroup group = part.ParentGroup; 1718 SceneObjectGroup group = part.ParentGroup;
1640 if (!affectedGroups.Contains(group)) 1719 if (!affectedGroups.Contains(group))
1720 {
1721 group.areUpdatesSuspended = true;
1641 affectedGroups.Add(group); 1722 affectedGroups.Add(group);
1723 }
1642 } 1724 }
1643 } 1725 }
1644 } 1726 }
1645 1727
1646 foreach (SceneObjectPart child in childParts) 1728 if (childParts.Count > 0)
1647 { 1729 {
1648 // Unlink all child parts from their groups 1730 foreach (SceneObjectPart child in childParts)
1649 // 1731 {
1650 child.ParentGroup.DelinkFromGroup(child, true); 1732 // Unlink all child parts from their groups
1651 1733 //
1652 // These are not in affected groups and will not be 1734 child.ParentGroup.DelinkFromGroup(child, true);
1653 // handled further. Do the honors here. 1735 child.ParentGroup.HasGroupChanged = true;
1654 child.ParentGroup.HasGroupChanged = true; 1736 child.ParentGroup.ScheduleGroupForFullUpdate();
1655 child.ParentGroup.ScheduleGroupForFullUpdate(); 1737 }
1656 } 1738 }
1657 1739
1658 foreach (SceneObjectPart root in rootParts) 1740 foreach (SceneObjectPart root in rootParts)
@@ -1662,56 +1744,68 @@ namespace OpenSim.Region.Framework.Scenes
1662 // However, editing linked parts and unlinking may be different 1744 // However, editing linked parts and unlinking may be different
1663 // 1745 //
1664 SceneObjectGroup group = root.ParentGroup; 1746 SceneObjectGroup group = root.ParentGroup;
1747 group.areUpdatesSuspended = true;
1665 1748
1666 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1749 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1667 int numChildren = newSet.Count; 1750 int numChildren = newSet.Count;
1668 1751
1752 if (numChildren == 1)
1753 break;
1754
1669 // If there are prims left in a link set, but the root is 1755 // If there are prims left in a link set, but the root is
1670 // slated for unlink, we need to do this 1756 // slated for unlink, we need to do this
1757 // Unlink the remaining set
1671 // 1758 //
1672 if (numChildren != 1) 1759 bool sendEventsToRemainder = true;
1673 { 1760 if (numChildren > 1)
1674 // Unlink the remaining set 1761 sendEventsToRemainder = false;
1675 //
1676 bool sendEventsToRemainder = true;
1677 if (numChildren > 1)
1678 sendEventsToRemainder = false;
1679 1762
1680 foreach (SceneObjectPart p in newSet) 1763 foreach (SceneObjectPart p in newSet)
1764 {
1765 if (p != group.RootPart)
1681 { 1766 {
1682 if (p != group.RootPart) 1767 group.DelinkFromGroup(p, sendEventsToRemainder);
1683 group.DelinkFromGroup(p, sendEventsToRemainder); 1768 if (numChildren > 2)
1769 {
1770 p.ParentGroup.areUpdatesSuspended = true;
1771 }
1772 else
1773 {
1774 p.ParentGroup.HasGroupChanged = true;
1775 p.ParentGroup.ScheduleGroupForFullUpdate();
1776 }
1684 } 1777 }
1778 }
1685 1779
1686 // If there is more than one prim remaining, we 1780 // If there is more than one prim remaining, we
1687 // need to re-link 1781 // need to re-link
1782 //
1783 if (numChildren > 2)
1784 {
1785 // Remove old root
1786 //
1787 if (newSet.Contains(root))
1788 newSet.Remove(root);
1789
1790 // Preserve link ordering
1688 // 1791 //
1689 if (numChildren > 2) 1792 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1690 { 1793 {
1691 // Remove old root 1794 return a.LinkNum.CompareTo(b.LinkNum);
1692 // 1795 });
1693 if (newSet.Contains(root))
1694 newSet.Remove(root);
1695
1696 // Preserve link ordering
1697 //
1698 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1699 {
1700 return a.LinkNum.CompareTo(b.LinkNum);
1701 });
1702 1796
1703 // Determine new root 1797 // Determine new root
1704 // 1798 //
1705 SceneObjectPart newRoot = newSet[0]; 1799 SceneObjectPart newRoot = newSet[0];
1706 newSet.RemoveAt(0); 1800 newSet.RemoveAt(0);
1707 1801
1708 foreach (SceneObjectPart newChild in newSet) 1802 foreach (SceneObjectPart newChild in newSet)
1709 newChild.UpdateFlag = 0; 1803 newChild.UpdateFlag = 0;
1710 1804
1711 LinkObjects(newRoot, newSet); 1805 newRoot.ParentGroup.areUpdatesSuspended = true;
1712 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1806 LinkObjects(newRoot, newSet);
1713 affectedGroups.Add(newRoot.ParentGroup); 1807 if (!affectedGroups.Contains(newRoot.ParentGroup))
1714 } 1808 affectedGroups.Add(newRoot.ParentGroup);
1715 } 1809 }
1716 } 1810 }
1717 1811
@@ -1719,8 +1813,14 @@ namespace OpenSim.Region.Framework.Scenes
1719 // 1813 //
1720 foreach (SceneObjectGroup g in affectedGroups) 1814 foreach (SceneObjectGroup g in affectedGroups)
1721 { 1815 {
1816 // Child prims that have been unlinked and deleted will
1817 // return unless the root is deleted. This will remove them
1818 // from the database. They will be rewritten immediately,
1819 // minus the rows for the unlinked child prims.
1820 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1722 g.TriggerScriptChangedEvent(Changed.LINK); 1821 g.TriggerScriptChangedEvent(Changed.LINK);
1723 g.HasGroupChanged = true; // Persist 1822 g.HasGroupChanged = true; // Persist
1823 g.areUpdatesSuspended = false;
1724 g.ScheduleGroupForFullUpdate(); 1824 g.ScheduleGroupForFullUpdate();
1725 } 1825 }
1726 } 1826 }
@@ -1838,9 +1938,6 @@ namespace OpenSim.Region.Framework.Scenes
1838 child.ApplyNextOwnerPermissions(); 1938 child.ApplyNextOwnerPermissions();
1839 } 1939 }
1840 } 1940 }
1841
1842 copy.RootPart.ObjectSaleType = 0;
1843 copy.RootPart.SalePrice = 10;
1844 } 1941 }
1845 1942
1846 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 1943 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 4bca3d0..9f0ac4f 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -69,10 +69,6 @@ namespace OpenSim.Region.Framework.Scenes
69 /// <summary> 69 /// <summary>
70 /// Stop the scripts contained in all the prims in this group 70 /// Stop the scripts contained in all the prims in this group
71 /// </summary> 71 /// </summary>
72 /// <param name="sceneObjectBeingDeleted">
73 /// Should be true if these scripts are being removed because the scene
74 /// object is being deleted. This will prevent spurious updates to the client.
75 /// </param>
76 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 72 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
77 { 73 {
78 SceneObjectPart[] parts = m_parts.GetArray(); 74 SceneObjectPart[] parts = m_parts.GetArray();
@@ -385,6 +381,9 @@ namespace OpenSim.Region.Framework.Scenes
385 381
386 public void ResumeScripts() 382 public void ResumeScripts()
387 { 383 {
384 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
385 return;
386
388 SceneObjectPart[] parts = m_parts.GetArray(); 387 SceneObjectPart[] parts = m_parts.GetArray();
389 for (int i = 0; i < parts.Length; i++) 388 for (int i = 0; i < parts.Length; i++)
390 parts[i].Inventory.ResumeScripts(); 389 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index 19a9506..b100b39 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
@@ -305,7 +374,11 @@ namespace OpenSim.Region.Framework.Scenes
305 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 374 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
306 } 375 }
307 } 376 }
308 377
378 foreach (SceneObjectPart part in m_parts.GetArray())
379 {
380 part.IgnoreUndoUpdate = true;
381 }
309 if (RootPart.GetStatusSandbox()) 382 if (RootPart.GetStatusSandbox())
310 { 383 {
311 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 384 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -319,10 +392,31 @@ namespace OpenSim.Region.Framework.Scenes
319 return; 392 return;
320 } 393 }
321 } 394 }
322
323 SceneObjectPart[] parts = m_parts.GetArray(); 395 SceneObjectPart[] parts = m_parts.GetArray();
324 for (int i = 0; i < parts.Length; i++) 396 foreach (SceneObjectPart part in parts)
325 parts[i].GroupPosition = val; 397 {
398 part.IgnoreUndoUpdate = false;
399 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
400 part.GroupPosition = val;
401 if (!m_dupeInProgress)
402 {
403 part.TriggerScriptChangedEvent(Changed.POSITION);
404 }
405 }
406 if (!m_dupeInProgress)
407 {
408 foreach (ScenePresence av in m_linkedAvatars)
409 {
410 SceneObjectPart p;
411 if (m_parts.TryGetValue(av.LinkedPrim, out p))
412 {
413 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
414 av.AbsolutePosition += offset;
415 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
416 av.SendAvatarDataToAllAgents();
417 }
418 }
419 }
326 420
327 //if (m_rootPart.PhysActor != null) 421 //if (m_rootPart.PhysActor != null)
328 //{ 422 //{
@@ -476,6 +570,7 @@ namespace OpenSim.Region.Framework.Scenes
476 /// </summary> 570 /// </summary>
477 public SceneObjectGroup() 571 public SceneObjectGroup()
478 { 572 {
573
479 } 574 }
480 575
481 /// <summary> 576 /// <summary>
@@ -492,7 +587,7 @@ namespace OpenSim.Region.Framework.Scenes
492 /// Constructor. This object is added to the scene later via AttachToScene() 587 /// Constructor. This object is added to the scene later via AttachToScene()
493 /// </summary> 588 /// </summary>
494 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 589 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
495 { 590 {
496 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 591 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
497 } 592 }
498 593
@@ -540,6 +635,9 @@ namespace OpenSim.Region.Framework.Scenes
540 /// </summary> 635 /// </summary>
541 public virtual void AttachToBackup() 636 public virtual void AttachToBackup()
542 { 637 {
638 if (IsAttachment) return;
639 m_scene.SceneGraph.FireAttachToBackup(this);
640
543 if (InSceneBackup) 641 if (InSceneBackup)
544 { 642 {
545 //m_log.DebugFormat( 643 //m_log.DebugFormat(
@@ -655,9 +753,9 @@ namespace OpenSim.Region.Framework.Scenes
655 result.normal = inter.normal; 753 result.normal = inter.normal;
656 result.distance = inter.distance; 754 result.distance = inter.distance;
657 } 755 }
756
658 } 757 }
659 } 758 }
660
661 return result; 759 return result;
662 } 760 }
663 761
@@ -677,17 +775,19 @@ namespace OpenSim.Region.Framework.Scenes
677 minZ = 8192f; 775 minZ = 8192f;
678 776
679 SceneObjectPart[] parts = m_parts.GetArray(); 777 SceneObjectPart[] parts = m_parts.GetArray();
680 for (int i = 0; i < parts.Length; i++) 778 foreach (SceneObjectPart part in parts)
681 { 779 {
682 SceneObjectPart part = parts[i];
683
684 Vector3 worldPos = part.GetWorldPosition(); 780 Vector3 worldPos = part.GetWorldPosition();
685 Vector3 offset = worldPos - AbsolutePosition; 781 Vector3 offset = worldPos - AbsolutePosition;
686 Quaternion worldRot; 782 Quaternion worldRot;
687 if (part.ParentID == 0) 783 if (part.ParentID == 0)
784 {
688 worldRot = part.RotationOffset; 785 worldRot = part.RotationOffset;
786 }
689 else 787 else
788 {
690 worldRot = part.GetWorldRotation(); 789 worldRot = part.GetWorldRotation();
790 }
691 791
692 Vector3 frontTopLeft; 792 Vector3 frontTopLeft;
693 Vector3 frontTopRight; 793 Vector3 frontTopRight;
@@ -699,6 +799,8 @@ namespace OpenSim.Region.Framework.Scenes
699 Vector3 backBottomLeft; 799 Vector3 backBottomLeft;
700 Vector3 backBottomRight; 800 Vector3 backBottomRight;
701 801
802 // Vector3[] corners = new Vector3[8];
803
702 Vector3 orig = Vector3.Zero; 804 Vector3 orig = Vector3.Zero;
703 805
704 frontTopLeft.X = orig.X - (part.Scale.X / 2); 806 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -733,6 +835,38 @@ namespace OpenSim.Region.Framework.Scenes
733 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 835 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
734 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 836 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
735 837
838
839
840 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
841 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
842 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
843 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
844 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
845 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
846 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
847 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
848
849 //for (int i = 0; i < 8; i++)
850 //{
851 // corners[i] = corners[i] * worldRot;
852 // corners[i] += offset;
853
854 // if (corners[i].X > maxX)
855 // maxX = corners[i].X;
856 // if (corners[i].X < minX)
857 // minX = corners[i].X;
858
859 // if (corners[i].Y > maxY)
860 // maxY = corners[i].Y;
861 // if (corners[i].Y < minY)
862 // minY = corners[i].Y;
863
864 // if (corners[i].Z > maxZ)
865 // maxZ = corners[i].Y;
866 // if (corners[i].Z < minZ)
867 // minZ = corners[i].Z;
868 //}
869
736 frontTopLeft = frontTopLeft * worldRot; 870 frontTopLeft = frontTopLeft * worldRot;
737 frontTopRight = frontTopRight * worldRot; 871 frontTopRight = frontTopRight * worldRot;
738 frontBottomLeft = frontBottomLeft * worldRot; 872 frontBottomLeft = frontBottomLeft * worldRot;
@@ -754,6 +888,15 @@ namespace OpenSim.Region.Framework.Scenes
754 backTopLeft += offset; 888 backTopLeft += offset;
755 backTopRight += offset; 889 backTopRight += offset;
756 890
891 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
892 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
893 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
894 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
895 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
896 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
897 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
898 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
899
757 if (frontTopRight.X > maxX) 900 if (frontTopRight.X > maxX)
758 maxX = frontTopRight.X; 901 maxX = frontTopRight.X;
759 if (frontTopLeft.X > maxX) 902 if (frontTopLeft.X > maxX)
@@ -899,15 +1042,20 @@ namespace OpenSim.Region.Framework.Scenes
899 1042
900 public void SaveScriptedState(XmlTextWriter writer) 1043 public void SaveScriptedState(XmlTextWriter writer)
901 { 1044 {
1045 SaveScriptedState(writer, false);
1046 }
1047
1048 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1049 {
902 XmlDocument doc = new XmlDocument(); 1050 XmlDocument doc = new XmlDocument();
903 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1051 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
904 1052
905 SceneObjectPart[] parts = m_parts.GetArray(); 1053 SceneObjectPart[] parts = m_parts.GetArray();
906 for (int i = 0; i < parts.Length; i++) 1054 for (int i = 0; i < parts.Length; i++)
907 { 1055 {
908 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1056 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
909 foreach (KeyValuePair<UUID, string> kvp in pstates) 1057 foreach (KeyValuePair<UUID, string> kvp in pstates)
910 states.Add(kvp.Key, kvp.Value); 1058 states[kvp.Key] = kvp.Value;
911 } 1059 }
912 1060
913 if (states.Count > 0) 1061 if (states.Count > 0)
@@ -926,6 +1074,118 @@ namespace OpenSim.Region.Framework.Scenes
926 } 1074 }
927 } 1075 }
928 1076
1077 /// <summary>
1078 /// Add the avatar to this linkset (avatar is sat).
1079 /// </summary>
1080 /// <param name="agentID"></param>
1081 public void AddAvatar(UUID agentID)
1082 {
1083 ScenePresence presence;
1084 if (m_scene.TryGetScenePresence(agentID, out presence))
1085 {
1086 if (!m_linkedAvatars.Contains(presence))
1087 {
1088 m_linkedAvatars.Add(presence);
1089 }
1090 }
1091 }
1092
1093 /// <summary>
1094 /// Delete the avatar from this linkset (avatar is unsat).
1095 /// </summary>
1096 /// <param name="agentID"></param>
1097 public void DeleteAvatar(UUID agentID)
1098 {
1099 ScenePresence presence;
1100 if (m_scene.TryGetScenePresence(agentID, out presence))
1101 {
1102 if (m_linkedAvatars.Contains(presence))
1103 {
1104 m_linkedAvatars.Remove(presence);
1105 }
1106 }
1107 }
1108
1109 /// <summary>
1110 /// Returns the list of linked presences (avatars sat on this group)
1111 /// </summary>
1112 /// <param name="agentID"></param>
1113 public List<ScenePresence> GetLinkedAvatars()
1114 {
1115 return m_linkedAvatars;
1116 }
1117
1118 /// <summary>
1119 /// Attach this scene object to the given avatar.
1120 /// </summary>
1121 /// <param name="agentID"></param>
1122 /// <param name="attachmentpoint"></param>
1123 /// <param name="AttachOffset"></param>
1124 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent)
1125 {
1126 ScenePresence avatar = m_scene.GetScenePresence(agentID);
1127 if (avatar != null)
1128 {
1129 // don't attach attachments to child agents
1130 if (avatar.IsChildAgent) return;
1131
1132// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
1133
1134 DetachFromBackup();
1135
1136 // Remove from database and parcel prim count
1137 m_scene.DeleteFromStorage(UUID);
1138 m_scene.EventManager.TriggerParcelPrimCountTainted();
1139
1140 m_rootPart.AttachedAvatar = agentID;
1141
1142 //Anakin Lohner bug #3839
1143 lock (m_parts)
1144 {
1145 foreach (SceneObjectPart p in m_parts.GetArray())
1146 {
1147 p.AttachedAvatar = agentID;
1148 }
1149 }
1150
1151 if (m_rootPart.PhysActor != null)
1152 {
1153 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor);
1154 m_rootPart.PhysActor = null;
1155 }
1156
1157 AbsolutePosition = AttachOffset;
1158 m_rootPart.AttachedPos = AttachOffset;
1159 m_rootPart.IsAttachment = true;
1160
1161 m_rootPart.SetParentLocalId(avatar.LocalId);
1162 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
1163
1164 avatar.AddAttachment(this);
1165
1166 if (!silent)
1167 {
1168 // Killing it here will cause the client to deselect it
1169 // It then reappears on the avatar, deselected
1170 // through the full update below
1171 //
1172 if (IsSelected)
1173 {
1174 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1175 }
1176
1177 IsSelected = false; // fudge....
1178 ScheduleGroupForFullUpdate();
1179 }
1180 }
1181 else
1182 {
1183 m_log.WarnFormat(
1184 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1185 UUID, agentID, Scene.RegionInfo.RegionName);
1186 }
1187 }
1188
929 public byte GetAttachmentPoint() 1189 public byte GetAttachmentPoint()
930 { 1190 {
931 return m_rootPart.Shape.State; 1191 return m_rootPart.Shape.State;
@@ -1052,7 +1312,10 @@ namespace OpenSim.Region.Framework.Scenes
1052 public void AddPart(SceneObjectPart part) 1312 public void AddPart(SceneObjectPart part)
1053 { 1313 {
1054 part.SetParent(this); 1314 part.SetParent(this);
1055 part.LinkNum = m_parts.Add(part.UUID, part); 1315 m_parts.Add(part.UUID, part);
1316
1317 part.LinkNum = m_parts.Count;
1318
1056 if (part.LinkNum == 2 && RootPart != null) 1319 if (part.LinkNum == 2 && RootPart != null)
1057 RootPart.LinkNum = 1; 1320 RootPart.LinkNum = 1;
1058 } 1321 }
@@ -1136,7 +1399,7 @@ namespace OpenSim.Region.Framework.Scenes
1136 1399
1137 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1400 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1138 { 1401 {
1139 part.StoreUndoState(); 1402 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1140 part.OnGrab(offsetPos, remoteClient); 1403 part.OnGrab(offsetPos, remoteClient);
1141 } 1404 }
1142 1405
@@ -1156,6 +1419,11 @@ namespace OpenSim.Region.Framework.Scenes
1156 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1419 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1157 public void DeleteGroupFromScene(bool silent) 1420 public void DeleteGroupFromScene(bool silent)
1158 { 1421 {
1422 // We need to keep track of this state in case this group is still queued for backup.
1423 m_isDeleted = true;
1424
1425 DetachFromBackup();
1426
1159 SceneObjectPart[] parts = m_parts.GetArray(); 1427 SceneObjectPart[] parts = m_parts.GetArray();
1160 for (int i = 0; i < parts.Length; i++) 1428 for (int i = 0; i < parts.Length; i++)
1161 { 1429 {
@@ -1167,13 +1435,11 @@ namespace OpenSim.Region.Framework.Scenes
1167 avatar.StandUp(); 1435 avatar.StandUp();
1168 1436
1169 if (!silent) 1437 if (!silent)
1170 {
1171 part.UpdateFlag = 0; 1438 part.UpdateFlag = 0;
1172 if (part == m_rootPart)
1173 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1174 }
1175 }); 1439 });
1176 } 1440 }
1441
1442
1177 } 1443 }
1178 1444
1179 public void AddScriptLPS(int count) 1445 public void AddScriptLPS(int count)
@@ -1270,7 +1536,12 @@ namespace OpenSim.Region.Framework.Scenes
1270 1536
1271 public void SetOwnerId(UUID userId) 1537 public void SetOwnerId(UUID userId)
1272 { 1538 {
1273 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1539 ForEachPart(delegate(SceneObjectPart part)
1540 {
1541
1542 part.OwnerID = userId;
1543
1544 });
1274 } 1545 }
1275 1546
1276 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1547 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1302,11 +1573,17 @@ namespace OpenSim.Region.Framework.Scenes
1302 return; 1573 return;
1303 } 1574 }
1304 1575
1576 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1577 return;
1578
1305 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1579 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1306 // any exception propogate upwards. 1580 // any exception propogate upwards.
1307 try 1581 try
1308 { 1582 {
1309 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1583 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1584 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1585 m_scene.LoadingPrims) // Land may not be valid yet
1586
1310 { 1587 {
1311 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1588 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1312 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1589 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1333,6 +1610,7 @@ namespace OpenSim.Region.Framework.Scenes
1333 } 1610 }
1334 } 1611 }
1335 } 1612 }
1613
1336 } 1614 }
1337 1615
1338 if (HasGroupChanged) 1616 if (HasGroupChanged)
@@ -1340,6 +1618,20 @@ namespace OpenSim.Region.Framework.Scenes
1340 // don't backup while it's selected or you're asking for changes mid stream. 1618 // don't backup while it's selected or you're asking for changes mid stream.
1341 if (isTimeToPersist() || forcedBackup) 1619 if (isTimeToPersist() || forcedBackup)
1342 { 1620 {
1621 if (m_rootPart.PhysActor != null &&
1622 (!m_rootPart.PhysActor.IsPhysical))
1623 {
1624 // Possible ghost prim
1625 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1626 {
1627 foreach (SceneObjectPart part in m_parts.GetArray())
1628 {
1629 // Re-set physics actor positions and
1630 // orientations
1631 part.GroupPosition = m_rootPart.GroupPosition;
1632 }
1633 }
1634 }
1343// m_log.DebugFormat( 1635// m_log.DebugFormat(
1344// "[SCENE]: Storing {0}, {1} in {2}", 1636// "[SCENE]: Storing {0}, {1} in {2}",
1345// Name, UUID, m_scene.RegionInfo.RegionName); 1637// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1403,81 +1695,90 @@ namespace OpenSim.Region.Framework.Scenes
1403 /// <returns></returns> 1695 /// <returns></returns>
1404 public SceneObjectGroup Copy(bool userExposed) 1696 public SceneObjectGroup Copy(bool userExposed)
1405 { 1697 {
1406 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1698 SceneObjectGroup dupe;
1407 dupe.m_isBackedUp = false; 1699 try
1408 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1700 {
1409 1701 m_dupeInProgress = true;
1410 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1702 dupe = (SceneObjectGroup)MemberwiseClone();
1411 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1703 dupe.m_isBackedUp = false;
1412 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1704 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1413 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1414 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1415 // then restore it's attachment state
1416
1417 // This is only necessary when userExposed is false!
1418 1705
1419 bool previousAttachmentStatus = dupe.RootPart.IsAttachment; 1706 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1420 1707 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1421 if (!userExposed) 1708 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1422 dupe.RootPart.IsAttachment = true; 1709 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1710 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1711 // then restore it's attachment state
1423 1712
1424 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1713 // This is only necessary when userExposed is false!
1425 1714
1426 if (!userExposed) 1715 bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
1427 {
1428 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1429 }
1430 1716
1431 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1717 if (!userExposed)
1432 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1718 dupe.RootPart.IsAttachment = true;
1433 1719
1434 if (userExposed) 1720 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1435 dupe.m_rootPart.TrimPermissions();
1436 1721
1437 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1722 if (!userExposed)
1438
1439 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1440 { 1723 {
1441 return p1.LinkNum.CompareTo(p2.LinkNum); 1724 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1442 } 1725 }
1443 );
1444 1726
1445 foreach (SceneObjectPart part in partList) 1727 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1446 { 1728 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1447 if (part.UUID != m_rootPart.UUID) 1729
1730 if (userExposed)
1731 dupe.m_rootPart.TrimPermissions();
1732
1733 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1734
1735 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1736 {
1737 return p1.LinkNum.CompareTo(p2.LinkNum);
1738 }
1739 );
1740
1741 foreach (SceneObjectPart part in partList)
1448 { 1742 {
1449 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1743 if (part.UUID != m_rootPart.UUID)
1450 newPart.LinkNum = part.LinkNum; 1744 {
1451 } 1745 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1452 1746
1453 // Need to duplicate the physics actor as well 1747 newPart.LinkNum = part.LinkNum;
1454 if (part.PhysActor != null && userExposed) 1748 }
1749
1750 // Need to duplicate the physics actor as well
1751 if (part.PhysActor != null && userExposed)
1752 {
1753 PrimitiveBaseShape pbs = part.Shape;
1754
1755 part.PhysActor
1756 = m_scene.PhysicsScene.AddPrimShape(
1757 string.Format("{0}/{1}", part.Name, part.UUID),
1758 pbs,
1759 part.AbsolutePosition,
1760 part.Scale,
1761 part.RotationOffset,
1762 part.PhysActor.IsPhysical);
1763 part.PhysActor.SetMaterial((int)part.Material);
1764
1765 part.PhysActor.LocalID = part.LocalId;
1766 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1767 }
1768 }
1769 if (userExposed)
1455 { 1770 {
1456 PrimitiveBaseShape pbs = part.Shape; 1771 dupe.UpdateParentIDs();
1457 1772 dupe.HasGroupChanged = true;
1458 part.PhysActor 1773 dupe.AttachToBackup();
1459 = m_scene.PhysicsScene.AddPrimShape( 1774
1460 string.Format("{0}/{1}", part.Name, part.UUID), 1775 ScheduleGroupForFullUpdate();
1461 pbs,
1462 part.AbsolutePosition,
1463 part.Scale,
1464 part.RotationOffset,
1465 part.PhysActor.IsPhysical);
1466
1467 part.PhysActor.LocalID = part.LocalId;
1468 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1469 } 1776 }
1470 } 1777 }
1471 1778 finally
1472 if (userExposed)
1473 { 1779 {
1474 dupe.UpdateParentIDs(); 1780 m_dupeInProgress = false;
1475 dupe.HasGroupChanged = true;
1476 dupe.AttachToBackup();
1477
1478 ScheduleGroupForFullUpdate();
1479 } 1781 }
1480
1481 return dupe; 1782 return dupe;
1482 } 1783 }
1483 1784
@@ -1622,6 +1923,7 @@ namespace OpenSim.Region.Framework.Scenes
1622 return Vector3.Zero; 1923 return Vector3.Zero;
1623 } 1924 }
1624 1925
1926 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1625 public void moveToTarget(Vector3 target, float tau) 1927 public void moveToTarget(Vector3 target, float tau)
1626 { 1928 {
1627 SceneObjectPart rootpart = m_rootPart; 1929 SceneObjectPart rootpart = m_rootPart;
@@ -1661,20 +1963,55 @@ namespace OpenSim.Region.Framework.Scenes
1661 SceneObjectPart rootpart = m_rootPart; 1963 SceneObjectPart rootpart = m_rootPart;
1662 if (rootpart != null) 1964 if (rootpart != null)
1663 { 1965 {
1664 if (rootpart.PhysActor != null) 1966 if (IsAttachment)
1967 {
1968 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1969 if (avatar != null) avatar.StopMoveToPosition();
1970 }
1971 else
1665 { 1972 {
1666 rootpart.PhysActor.PIDActive = false; 1973 if (rootpart.PhysActor != null)
1974 {
1975 rootpart.PhysActor.PIDActive = false;
1976 }
1667 } 1977 }
1668 } 1978 }
1669 } 1979 }
1670 1980
1981 public void rotLookAt(Quaternion target, float strength, float damping)
1982 {
1983 SceneObjectPart rootpart = m_rootPart;
1984 if (rootpart != null)
1985 {
1986 if (IsAttachment)
1987 {
1988 /*
1989 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1990 if (avatar != null)
1991 {
1992 Rotate the Av?
1993 } */
1994 }
1995 else
1996 {
1997 if (rootpart.PhysActor != null)
1998 { // APID must be implemented in your physics system for this to function.
1999 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2000 rootpart.PhysActor.APIDStrength = strength;
2001 rootpart.PhysActor.APIDDamping = damping;
2002 rootpart.PhysActor.APIDActive = true;
2003 }
2004 }
2005 }
2006 }
2007
1671 public void stopLookAt() 2008 public void stopLookAt()
1672 { 2009 {
1673 SceneObjectPart rootpart = m_rootPart; 2010 SceneObjectPart rootpart = m_rootPart;
1674 if (rootpart != null) 2011 if (rootpart != null)
1675 { 2012 {
1676 if (rootpart.PhysActor != null) 2013 if (rootpart.PhysActor != null)
1677 { 2014 { // APID must be implemented in your physics system for this to function.
1678 rootpart.PhysActor.APIDActive = false; 2015 rootpart.PhysActor.APIDActive = false;
1679 } 2016 }
1680 } 2017 }
@@ -1740,6 +2077,8 @@ namespace OpenSim.Region.Framework.Scenes
1740 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2077 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1741 { 2078 {
1742 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2079 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2080 newPart.SetParent(this);
2081
1743 AddPart(newPart); 2082 AddPart(newPart);
1744 2083
1745 SetPartAsNonRoot(newPart); 2084 SetPartAsNonRoot(newPart);
@@ -1888,11 +2227,11 @@ namespace OpenSim.Region.Framework.Scenes
1888 /// Immediately send a full update for this scene object. 2227 /// Immediately send a full update for this scene object.
1889 /// </summary> 2228 /// </summary>
1890 public void SendGroupFullUpdate() 2229 public void SendGroupFullUpdate()
1891 { 2230 {
1892 if (IsDeleted) 2231 if (IsDeleted)
1893 return; 2232 return;
1894 2233
1895// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2234// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1896 2235
1897 RootPart.SendFullUpdateToAllClients(); 2236 RootPart.SendFullUpdateToAllClients();
1898 2237
@@ -2081,12 +2420,15 @@ namespace OpenSim.Region.Framework.Scenes
2081 part.LinkNum += objectGroup.PrimCount; 2420 part.LinkNum += objectGroup.PrimCount;
2082 } 2421 }
2083 } 2422 }
2423 }
2084 2424
2085 linkPart.LinkNum = 2; 2425 linkPart.LinkNum = 2;
2086 2426
2087 linkPart.SetParent(this); 2427 linkPart.SetParent(this);
2088 linkPart.CreateSelected = true; 2428 linkPart.CreateSelected = true;
2089 2429
2430 lock (m_parts.SyncRoot)
2431 {
2090 //if (linkPart.PhysActor != null) 2432 //if (linkPart.PhysActor != null)
2091 //{ 2433 //{
2092 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2434 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2244,6 +2586,8 @@ namespace OpenSim.Region.Framework.Scenes
2244 /// <param name="objectGroup"></param> 2586 /// <param name="objectGroup"></param>
2245 public virtual void DetachFromBackup() 2587 public virtual void DetachFromBackup()
2246 { 2588 {
2589 m_scene.SceneGraph.FireDetachFromBackup(this);
2590
2247 if (m_isBackedUp) 2591 if (m_isBackedUp)
2248 m_scene.EventManager.OnBackup -= ProcessBackup; 2592 m_scene.EventManager.OnBackup -= ProcessBackup;
2249 2593
@@ -2262,7 +2606,8 @@ namespace OpenSim.Region.Framework.Scenes
2262 2606
2263 axPos *= parentRot; 2607 axPos *= parentRot;
2264 part.OffsetPosition = axPos; 2608 part.OffsetPosition = axPos;
2265 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2609 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2610 part.GroupPosition = newPos;
2266 part.OffsetPosition = Vector3.Zero; 2611 part.OffsetPosition = Vector3.Zero;
2267 part.RotationOffset = worldRot; 2612 part.RotationOffset = worldRot;
2268 2613
@@ -2273,7 +2618,7 @@ namespace OpenSim.Region.Framework.Scenes
2273 2618
2274 part.LinkNum = linkNum; 2619 part.LinkNum = linkNum;
2275 2620
2276 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2621 part.OffsetPosition = newPos - AbsolutePosition;
2277 2622
2278 Quaternion rootRotation = m_rootPart.RotationOffset; 2623 Quaternion rootRotation = m_rootPart.RotationOffset;
2279 2624
@@ -2283,7 +2628,7 @@ namespace OpenSim.Region.Framework.Scenes
2283 2628
2284 parentRot = m_rootPart.RotationOffset; 2629 parentRot = m_rootPart.RotationOffset;
2285 oldRot = part.RotationOffset; 2630 oldRot = part.RotationOffset;
2286 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2631 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2287 part.RotationOffset = newRot; 2632 part.RotationOffset = newRot;
2288 } 2633 }
2289 2634
@@ -2534,8 +2879,12 @@ namespace OpenSim.Region.Framework.Scenes
2534 } 2879 }
2535 } 2880 }
2536 2881
2882 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2537 for (int i = 0; i < parts.Length; i++) 2883 for (int i = 0; i < parts.Length; i++)
2538 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2884 {
2885 if (parts[i] != RootPart)
2886 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2887 }
2539 } 2888 }
2540 } 2889 }
2541 2890
@@ -2548,6 +2897,17 @@ namespace OpenSim.Region.Framework.Scenes
2548 } 2897 }
2549 } 2898 }
2550 2899
2900
2901
2902 /// <summary>
2903 /// Gets the number of parts
2904 /// </summary>
2905 /// <returns></returns>
2906 public int GetPartCount()
2907 {
2908 return Parts.Count();
2909 }
2910
2551 /// <summary> 2911 /// <summary>
2552 /// Update the texture entry for this part 2912 /// Update the texture entry for this part
2553 /// </summary> 2913 /// </summary>
@@ -2609,11 +2969,9 @@ namespace OpenSim.Region.Framework.Scenes
2609 scale.Y = m_scene.m_maxNonphys; 2969 scale.Y = m_scene.m_maxNonphys;
2610 if (scale.Z > m_scene.m_maxNonphys) 2970 if (scale.Z > m_scene.m_maxNonphys)
2611 scale.Z = m_scene.m_maxNonphys; 2971 scale.Z = m_scene.m_maxNonphys;
2612
2613 SceneObjectPart part = GetChildPart(localID); 2972 SceneObjectPart part = GetChildPart(localID);
2614 if (part != null) 2973 if (part != null)
2615 { 2974 {
2616 part.Resize(scale);
2617 if (part.PhysActor != null) 2975 if (part.PhysActor != null)
2618 { 2976 {
2619 if (part.PhysActor.IsPhysical) 2977 if (part.PhysActor.IsPhysical)
@@ -2628,7 +2986,7 @@ namespace OpenSim.Region.Framework.Scenes
2628 part.PhysActor.Size = scale; 2986 part.PhysActor.Size = scale;
2629 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2987 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2630 } 2988 }
2631 //if (part.UUID != m_rootPart.UUID) 2989 part.Resize(scale);
2632 2990
2633 HasGroupChanged = true; 2991 HasGroupChanged = true;
2634 part.TriggerScriptChangedEvent(Changed.SCALE); 2992 part.TriggerScriptChangedEvent(Changed.SCALE);
@@ -2651,7 +3009,6 @@ namespace OpenSim.Region.Framework.Scenes
2651 SceneObjectPart part = GetChildPart(localID); 3009 SceneObjectPart part = GetChildPart(localID);
2652 if (part != null) 3010 if (part != null)
2653 { 3011 {
2654 part.IgnoreUndoUpdate = true;
2655 if (scale.X > m_scene.m_maxNonphys) 3012 if (scale.X > m_scene.m_maxNonphys)
2656 scale.X = m_scene.m_maxNonphys; 3013 scale.X = m_scene.m_maxNonphys;
2657 if (scale.Y > m_scene.m_maxNonphys) 3014 if (scale.Y > m_scene.m_maxNonphys)
@@ -2688,7 +3045,7 @@ namespace OpenSim.Region.Framework.Scenes
2688 3045
2689 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3046 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2690 { 3047 {
2691 if (oldSize.X * x > m_scene.m_maxPhys) 3048 if (oldSize.X*x > m_scene.m_maxPhys)
2692 { 3049 {
2693 f = m_scene.m_maxPhys / oldSize.X; 3050 f = m_scene.m_maxPhys / oldSize.X;
2694 a = f / x; 3051 a = f / x;
@@ -2696,7 +3053,7 @@ namespace OpenSim.Region.Framework.Scenes
2696 y *= a; 3053 y *= a;
2697 z *= a; 3054 z *= a;
2698 } 3055 }
2699 if (oldSize.Y * y > m_scene.m_maxPhys) 3056 if (oldSize.Y*y > m_scene.m_maxPhys)
2700 { 3057 {
2701 f = m_scene.m_maxPhys / oldSize.Y; 3058 f = m_scene.m_maxPhys / oldSize.Y;
2702 a = f / y; 3059 a = f / y;
@@ -2704,7 +3061,7 @@ namespace OpenSim.Region.Framework.Scenes
2704 y *= a; 3061 y *= a;
2705 z *= a; 3062 z *= a;
2706 } 3063 }
2707 if (oldSize.Z * z > m_scene.m_maxPhys) 3064 if (oldSize.Z*z > m_scene.m_maxPhys)
2708 { 3065 {
2709 f = m_scene.m_maxPhys / oldSize.Z; 3066 f = m_scene.m_maxPhys / oldSize.Z;
2710 a = f / z; 3067 a = f / z;
@@ -2715,7 +3072,7 @@ namespace OpenSim.Region.Framework.Scenes
2715 } 3072 }
2716 else 3073 else
2717 { 3074 {
2718 if (oldSize.X * x > m_scene.m_maxNonphys) 3075 if (oldSize.X*x > m_scene.m_maxNonphys)
2719 { 3076 {
2720 f = m_scene.m_maxNonphys / oldSize.X; 3077 f = m_scene.m_maxNonphys / oldSize.X;
2721 a = f / x; 3078 a = f / x;
@@ -2723,7 +3080,7 @@ namespace OpenSim.Region.Framework.Scenes
2723 y *= a; 3080 y *= a;
2724 z *= a; 3081 z *= a;
2725 } 3082 }
2726 if (oldSize.Y * y > m_scene.m_maxNonphys) 3083 if (oldSize.Y*y > m_scene.m_maxNonphys)
2727 { 3084 {
2728 f = m_scene.m_maxNonphys / oldSize.Y; 3085 f = m_scene.m_maxNonphys / oldSize.Y;
2729 a = f / y; 3086 a = f / y;
@@ -2731,7 +3088,7 @@ namespace OpenSim.Region.Framework.Scenes
2731 y *= a; 3088 y *= a;
2732 z *= a; 3089 z *= a;
2733 } 3090 }
2734 if (oldSize.Z * z > m_scene.m_maxNonphys) 3091 if (oldSize.Z*z > m_scene.m_maxNonphys)
2735 { 3092 {
2736 f = m_scene.m_maxNonphys / oldSize.Z; 3093 f = m_scene.m_maxNonphys / oldSize.Z;
2737 a = f / z; 3094 a = f / z;
@@ -2741,7 +3098,6 @@ namespace OpenSim.Region.Framework.Scenes
2741 } 3098 }
2742 } 3099 }
2743 obPart.IgnoreUndoUpdate = false; 3100 obPart.IgnoreUndoUpdate = false;
2744 obPart.StoreUndoState();
2745 } 3101 }
2746 } 3102 }
2747 } 3103 }
@@ -2749,8 +3105,13 @@ namespace OpenSim.Region.Framework.Scenes
2749 Vector3 prevScale = part.Scale; 3105 Vector3 prevScale = part.Scale;
2750 prevScale.X *= x; 3106 prevScale.X *= x;
2751 prevScale.Y *= y; 3107 prevScale.Y *= y;
2752 prevScale.Z *= z; 3108 prevScale.Z *= z;;
3109
3110 part.IgnoreUndoUpdate = false;
3111 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3112 part.IgnoreUndoUpdate = true;
2753 part.Resize(prevScale); 3113 part.Resize(prevScale);
3114 part.IgnoreUndoUpdate = false;
2754 3115
2755 parts = m_parts.GetArray(); 3116 parts = m_parts.GetArray();
2756 for (int i = 0; i < parts.Length; i++) 3117 for (int i = 0; i < parts.Length; i++)
@@ -2759,19 +3120,26 @@ namespace OpenSim.Region.Framework.Scenes
2759 obPart.IgnoreUndoUpdate = true; 3120 obPart.IgnoreUndoUpdate = true;
2760 if (obPart.UUID != m_rootPart.UUID) 3121 if (obPart.UUID != m_rootPart.UUID)
2761 { 3122 {
2762 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3123 if (obPart.UUID != m_rootPart.UUID)
2763 currentpos.X *= x; 3124 {
2764 currentpos.Y *= y; 3125 obPart.IgnoreUndoUpdate = false;
2765 currentpos.Z *= z; 3126 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
2766 Vector3 newSize = new Vector3(obPart.Scale); 3127 obPart.IgnoreUndoUpdate = true;
2767 newSize.X *= x; 3128
2768 newSize.Y *= y; 3129 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2769 newSize.Z *= z; 3130 currentpos.X *= x;
2770 obPart.Resize(newSize); 3131 currentpos.Y *= y;
2771 obPart.UpdateOffSet(currentpos); 3132 currentpos.Z *= z;
3133 Vector3 newSize = new Vector3(obPart.Scale);
3134 newSize.X *= x;
3135 newSize.Y *= y;
3136 newSize.Z *= z;
3137 obPart.Resize(newSize);
3138 obPart.UpdateOffSet(currentpos);
3139 }
3140 obPart.IgnoreUndoUpdate = false;
2772 } 3141 }
2773 obPart.IgnoreUndoUpdate = false; 3142 obPart.IgnoreUndoUpdate = false;
2774 obPart.StoreUndoState();
2775 } 3143 }
2776 3144
2777 if (part.PhysActor != null) 3145 if (part.PhysActor != null)
@@ -2781,7 +3149,6 @@ namespace OpenSim.Region.Framework.Scenes
2781 } 3149 }
2782 3150
2783 part.IgnoreUndoUpdate = false; 3151 part.IgnoreUndoUpdate = false;
2784 part.StoreUndoState();
2785 HasGroupChanged = true; 3152 HasGroupChanged = true;
2786 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); 3153 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
2787 ScheduleGroupForTerseUpdate(); 3154 ScheduleGroupForTerseUpdate();
@@ -2798,14 +3165,11 @@ namespace OpenSim.Region.Framework.Scenes
2798 /// <param name="pos"></param> 3165 /// <param name="pos"></param>
2799 public void UpdateGroupPosition(Vector3 pos) 3166 public void UpdateGroupPosition(Vector3 pos)
2800 { 3167 {
2801 SceneObjectPart[] parts = m_parts.GetArray();
2802 for (int i = 0; i < parts.Length; i++)
2803 parts[i].StoreUndoState();
2804
2805 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3168 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2806 { 3169 {
2807 if (IsAttachment) 3170 if (IsAttachment)
2808 { 3171 {
3172 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2809 m_rootPart.AttachedPos = pos; 3173 m_rootPart.AttachedPos = pos;
2810 } 3174 }
2811 if (RootPart.GetStatusSandbox()) 3175 if (RootPart.GetStatusSandbox())
@@ -2839,7 +3203,7 @@ namespace OpenSim.Region.Framework.Scenes
2839 3203
2840 SceneObjectPart[] parts = m_parts.GetArray(); 3204 SceneObjectPart[] parts = m_parts.GetArray();
2841 for (int i = 0; i < parts.Length; i++) 3205 for (int i = 0; i < parts.Length; i++)
2842 parts[i].StoreUndoState(); 3206 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2843 3207
2844 if (part != null) 3208 if (part != null)
2845 { 3209 {
@@ -2864,7 +3228,7 @@ namespace OpenSim.Region.Framework.Scenes
2864 { 3228 {
2865 SceneObjectPart[] parts = m_parts.GetArray(); 3229 SceneObjectPart[] parts = m_parts.GetArray();
2866 for (int i = 0; i < parts.Length; i++) 3230 for (int i = 0; i < parts.Length; i++)
2867 parts[i].StoreUndoState(); 3231 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2868 3232
2869 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3233 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2870 Vector3 oldPos = 3234 Vector3 oldPos =
@@ -2885,10 +3249,27 @@ namespace OpenSim.Region.Framework.Scenes
2885 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3249 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2886 } 3250 }
2887 3251
2888 AbsolutePosition = newPos; 3252 //We have to set undoing here because otherwise an undo state will be saved
3253 if (!m_rootPart.Undoing)
3254 {
3255 m_rootPart.Undoing = true;
3256 AbsolutePosition = newPos;
3257 m_rootPart.Undoing = false;
3258 }
3259 else
3260 {
3261 AbsolutePosition = newPos;
3262 }
2889 3263
2890 HasGroupChanged = true; 3264 HasGroupChanged = true;
2891 ScheduleGroupForTerseUpdate(); 3265 if (m_rootPart.Undoing)
3266 {
3267 ScheduleGroupForFullUpdate();
3268 }
3269 else
3270 {
3271 ScheduleGroupForTerseUpdate();
3272 }
2892 } 3273 }
2893 3274
2894 public void OffsetForNewRegion(Vector3 offset) 3275 public void OffsetForNewRegion(Vector3 offset)
@@ -2908,7 +3289,7 @@ namespace OpenSim.Region.Framework.Scenes
2908 { 3289 {
2909 SceneObjectPart[] parts = m_parts.GetArray(); 3290 SceneObjectPart[] parts = m_parts.GetArray();
2910 for (int i = 0; i < parts.Length; i++) 3291 for (int i = 0; i < parts.Length; i++)
2911 parts[i].StoreUndoState(); 3292 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2912 3293
2913 m_rootPart.UpdateRotation(rot); 3294 m_rootPart.UpdateRotation(rot);
2914 3295
@@ -2932,7 +3313,7 @@ namespace OpenSim.Region.Framework.Scenes
2932 { 3313 {
2933 SceneObjectPart[] parts = m_parts.GetArray(); 3314 SceneObjectPart[] parts = m_parts.GetArray();
2934 for (int i = 0; i < parts.Length; i++) 3315 for (int i = 0; i < parts.Length; i++)
2935 parts[i].StoreUndoState(); 3316 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2936 3317
2937 m_rootPart.UpdateRotation(rot); 3318 m_rootPart.UpdateRotation(rot);
2938 3319
@@ -2957,10 +3338,9 @@ namespace OpenSim.Region.Framework.Scenes
2957 public void UpdateSingleRotation(Quaternion rot, uint localID) 3338 public void UpdateSingleRotation(Quaternion rot, uint localID)
2958 { 3339 {
2959 SceneObjectPart part = GetChildPart(localID); 3340 SceneObjectPart part = GetChildPart(localID);
2960
2961 SceneObjectPart[] parts = m_parts.GetArray(); 3341 SceneObjectPart[] parts = m_parts.GetArray();
2962 for (int i = 0; i < parts.Length; i++) 3342 for (int i = 0; i < parts.Length; i++)
2963 parts[i].StoreUndoState(); 3343 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2964 3344
2965 if (part != null) 3345 if (part != null)
2966 { 3346 {
@@ -2988,15 +3368,24 @@ namespace OpenSim.Region.Framework.Scenes
2988 if (part.UUID == m_rootPart.UUID) 3368 if (part.UUID == m_rootPart.UUID)
2989 { 3369 {
2990 UpdateRootRotation(rot); 3370 UpdateRootRotation(rot);
2991 AbsolutePosition = pos; 3371 if (!m_rootPart.Undoing)
3372 {
3373 m_rootPart.Undoing = true;
3374 AbsolutePosition = pos;
3375 m_rootPart.Undoing = false;
3376 }
3377 else
3378 {
3379 AbsolutePosition = pos;
3380 }
2992 } 3381 }
2993 else 3382 else
2994 { 3383 {
3384 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2995 part.IgnoreUndoUpdate = true; 3385 part.IgnoreUndoUpdate = true;
2996 part.UpdateRotation(rot); 3386 part.UpdateRotation(rot);
2997 part.OffsetPosition = pos; 3387 part.OffsetPosition = pos;
2998 part.IgnoreUndoUpdate = false; 3388 part.IgnoreUndoUpdate = false;
2999 part.StoreUndoState();
3000 } 3389 }
3001 } 3390 }
3002 } 3391 }
@@ -3010,8 +3399,16 @@ namespace OpenSim.Region.Framework.Scenes
3010 Quaternion axRot = rot; 3399 Quaternion axRot = rot;
3011 Quaternion oldParentRot = m_rootPart.RotationOffset; 3400 Quaternion oldParentRot = m_rootPart.RotationOffset;
3012 3401
3013 m_rootPart.StoreUndoState(); 3402 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3014 m_rootPart.UpdateRotation(rot); 3403 bool cancelUndo = false;
3404 if (!m_rootPart.Undoing)
3405 {
3406 m_rootPart.Undoing = true;
3407 cancelUndo = true;
3408 }
3409
3410 //Don't use UpdateRotation because it schedules an update prematurely
3411 m_rootPart.RotationOffset = rot;
3015 if (m_rootPart.PhysActor != null) 3412 if (m_rootPart.PhysActor != null)
3016 { 3413 {
3017 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3414 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -3026,28 +3423,22 @@ namespace OpenSim.Region.Framework.Scenes
3026 { 3423 {
3027 prim.IgnoreUndoUpdate = true; 3424 prim.IgnoreUndoUpdate = true;
3028 Vector3 axPos = prim.OffsetPosition; 3425 Vector3 axPos = prim.OffsetPosition;
3426
3029 axPos *= oldParentRot; 3427 axPos *= oldParentRot;
3030 axPos *= Quaternion.Inverse(axRot); 3428 axPos *= Quaternion.Inverse(axRot);
3031 prim.OffsetPosition = axPos; 3429 prim.OffsetPosition = axPos;
3032 Quaternion primsRot = prim.RotationOffset; 3430
3033 Quaternion newRot = primsRot * oldParentRot; 3431 prim.RotationOffset *= Quaternion.Inverse(prim.GetWorldRotation()) * (oldParentRot * prim.RotationOffset);
3034 newRot *= Quaternion.Inverse(axRot); 3432
3035 prim.RotationOffset = newRot; 3433 prim.IgnoreUndoUpdate = false;
3036 prim.ScheduleTerseUpdate();
3037 } 3434 }
3038 } 3435 }
3039 3436 if (cancelUndo == true)
3040 for (int i = 0; i < parts.Length; i++)
3041 { 3437 {
3042 SceneObjectPart childpart = parts[i]; 3438 m_rootPart.Undoing = false;
3043 if (childpart != m_rootPart)
3044 {
3045 childpart.IgnoreUndoUpdate = false;
3046 childpart.StoreUndoState();
3047 }
3048 } 3439 }
3049 3440 HasGroupChanged = true;
3050 m_rootPart.ScheduleTerseUpdate(); 3441 ScheduleGroupForFullUpdate();
3051 } 3442 }
3052 3443
3053 #endregion 3444 #endregion
@@ -3270,7 +3661,6 @@ namespace OpenSim.Region.Framework.Scenes
3270 public float GetMass() 3661 public float GetMass()
3271 { 3662 {
3272 float retmass = 0f; 3663 float retmass = 0f;
3273
3274 SceneObjectPart[] parts = m_parts.GetArray(); 3664 SceneObjectPart[] parts = m_parts.GetArray();
3275 for (int i = 0; i < parts.Length; i++) 3665 for (int i = 0; i < parts.Length; i++)
3276 retmass += parts[i].GetMass(); 3666 retmass += parts[i].GetMass();
@@ -3386,6 +3776,14 @@ namespace OpenSim.Region.Framework.Scenes
3386 SetFromItemID(uuid); 3776 SetFromItemID(uuid);
3387 } 3777 }
3388 3778
3779 public void ResetOwnerChangeFlag()
3780 {
3781 ForEachPart(delegate(SceneObjectPart part)
3782 {
3783 part.ResetOwnerChangeFlag();
3784 });
3785 }
3786
3389 #endregion 3787 #endregion
3390 } 3788 }
3391} 3789}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 8a8a699..e7e3014 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;
@@ -2075,19 +2113,17 @@ namespace OpenSim.Region.Framework.Scenes
2075 public Vector3 GetWorldPosition() 2113 public Vector3 GetWorldPosition()
2076 { 2114 {
2077 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2115 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2078
2079 Vector3 axPos = OffsetPosition; 2116 Vector3 axPos = OffsetPosition;
2080
2081 axPos *= parentRot; 2117 axPos *= parentRot;
2082 Vector3 translationOffsetPosition = axPos; 2118 Vector3 translationOffsetPosition = axPos;
2083 2119 if(_parentID == 0)
2084// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name); 2120 {
2085 2121 return GroupPosition;
2086 Vector3 worldPos = GroupPosition + translationOffsetPosition; 2122 }
2087 2123 else
2088// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name); 2124 {
2089 2125 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2090 return worldPos; 2126 }
2091 } 2127 }
2092 2128
2093 /// <summary> 2129 /// <summary>
@@ -2744,17 +2780,18 @@ namespace OpenSim.Region.Framework.Scenes
2744 //Trys to fetch sound id from prim's inventory. 2780 //Trys to fetch sound id from prim's inventory.
2745 //Prim's inventory doesn't support non script items yet 2781 //Prim's inventory doesn't support non script items yet
2746 2782
2747 lock (TaskInventory) 2783 TaskInventory.LockItemsForRead(true);
2784
2785 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2748 { 2786 {
2749 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2787 if (item.Value.Name == sound)
2750 { 2788 {
2751 if (item.Value.Name == sound) 2789 soundID = item.Value.ItemID;
2752 { 2790 break;
2753 soundID = item.Value.ItemID;
2754 break;
2755 }
2756 } 2791 }
2757 } 2792 }
2793
2794 TaskInventory.LockItemsForRead(false);
2758 } 2795 }
2759 2796
2760 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2797 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2814,7 +2851,7 @@ namespace OpenSim.Region.Framework.Scenes
2814 /// <param name="scale"></param> 2851 /// <param name="scale"></param>
2815 public void Resize(Vector3 scale) 2852 public void Resize(Vector3 scale)
2816 { 2853 {
2817 StoreUndoState(); 2854 StoreUndoState(UndoType.STATE_PRIM_SCALE);
2818 m_shape.Scale = scale; 2855 m_shape.Scale = scale;
2819 2856
2820 ParentGroup.HasGroupChanged = true; 2857 ParentGroup.HasGroupChanged = true;
@@ -2823,38 +2860,7 @@ namespace OpenSim.Region.Framework.Scenes
2823 2860
2824 public void RotLookAt(Quaternion target, float strength, float damping) 2861 public void RotLookAt(Quaternion target, float strength, float damping)
2825 { 2862 {
2826 rotLookAt(target, strength, damping); 2863 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2827 }
2828
2829 public void rotLookAt(Quaternion target, float strength, float damping)
2830 {
2831 if (IsAttachment)
2832 {
2833 /*
2834 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2835 if (avatar != null)
2836 {
2837 Rotate the Av?
2838 } */
2839 }
2840 else
2841 {
2842 APIDDamp = damping;
2843 APIDStrength = strength;
2844 APIDTarget = target;
2845 }
2846 }
2847
2848 public void startLookAt(Quaternion rot, float damp, float strength)
2849 {
2850 APIDDamp = damp;
2851 APIDStrength = strength;
2852 APIDTarget = rot;
2853 }
2854
2855 public void stopLookAt()
2856 {
2857 APIDTarget = Quaternion.Identity;
2858 } 2864 }
2859 2865
2860 /// <summary> 2866 /// <summary>
@@ -2866,7 +2872,10 @@ namespace OpenSim.Region.Framework.Scenes
2866 2872
2867 if (m_parentGroup != null) 2873 if (m_parentGroup != null)
2868 { 2874 {
2869 m_parentGroup.QueueForUpdateCheck(); 2875 if (!m_parentGroup.areUpdatesSuspended)
2876 {
2877 m_parentGroup.QueueForUpdateCheck();
2878 }
2870 } 2879 }
2871 2880
2872 int timeNow = Util.UnixTimeSinceEpoch(); 2881 int timeNow = Util.UnixTimeSinceEpoch();
@@ -3083,8 +3092,8 @@ namespace OpenSim.Region.Framework.Scenes
3083 { 3092 {
3084 const float ROTATION_TOLERANCE = 0.01f; 3093 const float ROTATION_TOLERANCE = 0.01f;
3085 const float VELOCITY_TOLERANCE = 0.001f; 3094 const float VELOCITY_TOLERANCE = 0.001f;
3086 const float POSITION_TOLERANCE = 0.05f; 3095 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3087 const int TIME_MS_TOLERANCE = 3000; 3096 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3088 3097
3089 if (m_updateFlag == 1) 3098 if (m_updateFlag == 1)
3090 { 3099 {
@@ -3098,7 +3107,7 @@ namespace OpenSim.Region.Framework.Scenes
3098 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3107 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3099 { 3108 {
3100 AddTerseUpdateToAllAvatars(); 3109 AddTerseUpdateToAllAvatars();
3101 ClearUpdateSchedule(); 3110
3102 3111
3103 // This causes the Scene to 'poll' physical objects every couple of frames 3112 // This causes the Scene to 'poll' physical objects every couple of frames
3104 // bad, so it's been replaced by an event driven method. 3113 // bad, so it's been replaced by an event driven method.
@@ -3116,16 +3125,18 @@ namespace OpenSim.Region.Framework.Scenes
3116 m_lastAngularVelocity = AngularVelocity; 3125 m_lastAngularVelocity = AngularVelocity;
3117 m_lastTerseSent = Environment.TickCount; 3126 m_lastTerseSent = Environment.TickCount;
3118 } 3127 }
3128 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3129 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3119 } 3130 }
3120 else 3131 else
3121 { 3132 {
3122 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3133 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3123 { 3134 {
3124 AddFullUpdateToAllAvatars(); 3135 AddFullUpdateToAllAvatars();
3125 ClearUpdateSchedule(); 3136 m_updateFlag = 0; //Same here
3126 } 3137 }
3127 } 3138 }
3128 ClearUpdateSchedule(); 3139 m_updateFlag = 0;
3129 } 3140 }
3130 3141
3131 /// <summary> 3142 /// <summary>
@@ -3153,17 +3164,16 @@ namespace OpenSim.Region.Framework.Scenes
3153 if (!UUID.TryParse(sound, out soundID)) 3164 if (!UUID.TryParse(sound, out soundID))
3154 { 3165 {
3155 // search sound file from inventory 3166 // search sound file from inventory
3156 lock (TaskInventory) 3167 TaskInventory.LockItemsForRead(true);
3168 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3157 { 3169 {
3158 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3170 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3159 { 3171 {
3160 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3172 soundID = item.Value.ItemID;
3161 { 3173 break;
3162 soundID = item.Value.ItemID;
3163 break;
3164 }
3165 } 3174 }
3166 } 3175 }
3176 TaskInventory.LockItemsForRead(false);
3167 } 3177 }
3168 3178
3169 if (soundID == UUID.Zero) 3179 if (soundID == UUID.Zero)
@@ -3593,7 +3603,7 @@ namespace OpenSim.Region.Framework.Scenes
3593 3603
3594 public void StopLookAt() 3604 public void StopLookAt()
3595 { 3605 {
3596 m_parentGroup.stopLookAt(); 3606 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3597 3607
3598 m_parentGroup.ScheduleGroupForTerseUpdate(); 3608 m_parentGroup.ScheduleGroupForTerseUpdate();
3599 } 3609 }
@@ -3620,10 +3630,9 @@ namespace OpenSim.Region.Framework.Scenes
3620 m_parentGroup.ScheduleGroupForTerseUpdate(); 3630 m_parentGroup.ScheduleGroupForTerseUpdate();
3621 //m_parentGroup.ScheduleGroupForFullUpdate(); 3631 //m_parentGroup.ScheduleGroupForFullUpdate();
3622 } 3632 }
3623 3633 public void StoreUndoState(UndoType type)
3624 public void StoreUndoState()
3625 { 3634 {
3626 if (!Undoing) 3635 if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing))
3627 { 3636 {
3628 if (!IgnoreUndoUpdate) 3637 if (!IgnoreUndoUpdate)
3629 { 3638 {
@@ -3634,17 +3643,25 @@ namespace OpenSim.Region.Framework.Scenes
3634 if (m_undo.Count > 0) 3643 if (m_undo.Count > 0)
3635 { 3644 {
3636 UndoState last = m_undo.Peek(); 3645 UndoState last = m_undo.Peek();
3637 if (last != null) 3646
3638 {
3639 if (last.Compare(this))
3640 return;
3641 }
3642 } 3647 }
3643 3648
3644 if (m_parentGroup.GetSceneMaxUndo() > 0) 3649 if (m_parentGroup.GetSceneMaxUndo() > 0)
3645 { 3650 {
3646 UndoState nUndo = new UndoState(this); 3651 UndoState lastUndo = m_undo.Peek();
3647 3652
3653 UndoState nUndo = new UndoState(this, type);
3654
3655 if (lastUndo != null)
3656 {
3657 TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated);
3658 if (ts.TotalMilliseconds < 500)
3659 {
3660 //Delete the last entry since it was less than 500 milliseconds ago
3661 nUndo.Merge(lastUndo);
3662 m_undo.Pop();
3663 }
3664 }
3648 m_undo.Push(nUndo); 3665 m_undo.Push(nUndo);
3649 } 3666 }
3650 3667
@@ -4121,11 +4138,13 @@ namespace OpenSim.Region.Framework.Scenes
4121 if (m_undo.Count > 0) 4138 if (m_undo.Count > 0)
4122 { 4139 {
4123 UndoState nUndo = null; 4140 UndoState nUndo = null;
4141 UndoState goback = m_undo.Pop();
4124 if (m_parentGroup.GetSceneMaxUndo() > 0) 4142 if (m_parentGroup.GetSceneMaxUndo() > 0)
4125 { 4143 {
4126 nUndo = new UndoState(this); 4144 nUndo = new UndoState(this, goback.Type);
4127 } 4145 }
4128 UndoState goback = m_undo.Pop(); 4146
4147
4129 if (goback != null) 4148 if (goback != null)
4130 { 4149 {
4131 goback.PlaybackState(this); 4150 goback.PlaybackState(this);
@@ -4140,13 +4159,13 @@ namespace OpenSim.Region.Framework.Scenes
4140 { 4159 {
4141 lock (m_redo) 4160 lock (m_redo)
4142 { 4161 {
4162 UndoState gofwd = m_redo.Pop();
4143 if (m_parentGroup.GetSceneMaxUndo() > 0) 4163 if (m_parentGroup.GetSceneMaxUndo() > 0)
4144 { 4164 {
4145 UndoState nUndo = new UndoState(this); 4165 UndoState nUndo = new UndoState(this, gofwd.Type);
4146 4166
4147 m_undo.Push(nUndo); 4167 m_undo.Push(nUndo);
4148 } 4168 }
4149 UndoState gofwd = m_redo.Pop();
4150 if (gofwd != null) 4169 if (gofwd != null)
4151 gofwd.PlayfwdState(this); 4170 gofwd.PlayfwdState(this);
4152 } 4171 }
@@ -4410,6 +4429,7 @@ namespace OpenSim.Region.Framework.Scenes
4410 Scale, 4429 Scale,
4411 RotationOffset, 4430 RotationOffset,
4412 UsePhysics); 4431 UsePhysics);
4432 PhysActor.SetMaterial(Material);
4413 4433
4414 pa = PhysActor; 4434 pa = PhysActor;
4415 if (pa != null) 4435 if (pa != null)
@@ -4595,8 +4615,9 @@ namespace OpenSim.Region.Framework.Scenes
4595 { 4615 {
4596 m_shape.TextureEntry = textureEntry; 4616 m_shape.TextureEntry = textureEntry;
4597 TriggerScriptChangedEvent(Changed.TEXTURE); 4617 TriggerScriptChangedEvent(Changed.TEXTURE);
4598 4618 m_updateFlag = 1;
4599 ParentGroup.HasGroupChanged = true; 4619 ParentGroup.HasGroupChanged = true;
4620
4600 //This is madness.. 4621 //This is madness..
4601 //ParentGroup.ScheduleGroupForFullUpdate(); 4622 //ParentGroup.ScheduleGroupForFullUpdate();
4602 //This is sparta 4623 //This is sparta
@@ -4829,5 +4850,17 @@ namespace OpenSim.Region.Framework.Scenes
4829 Color color = Color; 4850 Color color = Color;
4830 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4851 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4831 } 4852 }
4853
4854 public void ResetOwnerChangeFlag()
4855 {
4856 List<UUID> inv = Inventory.GetInventoryList();
4857
4858 foreach (UUID itemID in inv)
4859 {
4860 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4861 item.OwnerChanged = false;
4862 Inventory.UpdateInventoryItem(item, false, false);
4863 }
4864 }
4832 } 4865 }
4833} 4866}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3b60f8c..d135f16 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 156 }
149 foreach (TaskInventoryItem item in items) 157
150 { 158 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
151 item.ParentPartID = m_part.UUID; 159 Items.Clear();
152 item.ParentID = m_part.UUID; 160
153 Items.Add(item.ItemID, item); 161 foreach (TaskInventoryItem item in items)
154 } 162 {
163 item.ParentPartID = m_part.UUID;
164 item.ParentID = m_part.UUID;
165 Items.Add(item.ItemID, item);
155 } 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 item.OwnerChanged = true; 194 item.OwnerChanged = true;
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,8 +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) 881
882 if (m_items.ContainsKey(item.ItemID))
696 { 883 {
697// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 884// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
698 885
@@ -705,14 +892,10 @@ namespace OpenSim.Region.Framework.Scenes
705 item.GroupID = m_part.GroupID; 892 item.GroupID = m_part.GroupID;
706 893
707 if (item.AssetID == UUID.Zero) 894 if (item.AssetID == UUID.Zero)
708 item.AssetID = it.AssetID; 895 item.AssetID = m_items[item.ItemID].AssetID;
709 896
710 lock (m_items) 897 m_items[item.ItemID] = item;
711 { 898 m_inventorySerial++;
712 m_items[item.ItemID] = item;
713 m_inventorySerial++;
714 }
715
716 if (fireScriptEvents) 899 if (fireScriptEvents)
717 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 900 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
718 901
@@ -721,7 +904,7 @@ namespace OpenSim.Region.Framework.Scenes
721 HasInventoryChanged = true; 904 HasInventoryChanged = true;
722 m_part.ParentGroup.HasGroupChanged = true; 905 m_part.ParentGroup.HasGroupChanged = true;
723 } 906 }
724 907 m_items.LockItemsForWrite(false);
725 return true; 908 return true;
726 } 909 }
727 else 910 else
@@ -732,8 +915,9 @@ namespace OpenSim.Region.Framework.Scenes
732 item.ItemID, m_part.Name, m_part.UUID, 915 item.ItemID, m_part.Name, m_part.UUID,
733 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 916 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
734 } 917 }
735 return false; 918 m_items.LockItemsForWrite(false);
736 919
920 return false;
737 } 921 }
738 922
739 /// <summary> 923 /// <summary>
@@ -744,107 +928,68 @@ namespace OpenSim.Region.Framework.Scenes
744 /// in this prim's inventory.</returns> 928 /// in this prim's inventory.</returns>
745 public int RemoveInventoryItem(UUID itemID) 929 public int RemoveInventoryItem(UUID itemID)
746 { 930 {
747 TaskInventoryItem item = GetInventoryItem(itemID); 931 m_items.LockItemsForRead(true);
748 if (item != null) 932
933 if (m_items.ContainsKey(itemID))
749 { 934 {
750 int type = m_items[itemID].InvType; 935 int type = m_items[itemID].InvType;
936 m_items.LockItemsForRead(false);
751 if (type == 10) // Script 937 if (type == 10) // Script
752 { 938 {
753 m_part.RemoveScriptEvents(itemID);
754 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 939 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
755 } 940 }
941 m_items.LockItemsForWrite(true);
756 m_items.Remove(itemID); 942 m_items.Remove(itemID);
943 m_items.LockItemsForWrite(false);
757 m_inventorySerial++; 944 m_inventorySerial++;
758 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 945 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
759 946
760 HasInventoryChanged = true; 947 HasInventoryChanged = true;
761 m_part.ParentGroup.HasGroupChanged = true; 948 m_part.ParentGroup.HasGroupChanged = true;
762 949
763 if (!ContainsScripts()) 950 int scriptcount = 0;
951 m_items.LockItemsForRead(true);
952 foreach (TaskInventoryItem item in m_items.Values)
953 {
954 if (item.Type == 10)
955 {
956 scriptcount++;
957 }
958 }
959 m_items.LockItemsForRead(false);
960
961
962 if (scriptcount <= 0)
963 {
764 m_part.RemFlag(PrimFlags.Scripted); 964 m_part.RemFlag(PrimFlags.Scripted);
965 }
765 966
766 m_part.ScheduleFullUpdate(); 967 m_part.ScheduleFullUpdate();
767 968
768 return type; 969 return type;
769
770 } 970 }
771 else 971 else
772 { 972 {
973 m_items.LockItemsForRead(false);
773 m_log.ErrorFormat( 974 m_log.ErrorFormat(
774 "[PRIM INVENTORY]: " + 975 "[PRIM INVENTORY]: " +
775 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 976 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
776 itemID, m_part.Name, m_part.UUID, 977 itemID, m_part.Name, m_part.UUID);
777 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
778 } 978 }
779 979
780 return -1; 980 return -1;
781 } 981 }
782 982
783 private bool CreateInventoryFile() 983 private bool CreateInventoryFileName()
784 { 984 {
785 if (m_inventoryFileName == String.Empty || 985 if (m_inventoryFileName == String.Empty ||
786 m_inventoryFileNameSerial < m_inventorySerial) 986 m_inventoryFileNameSerial < m_inventorySerial)
787 { 987 {
788 // Something changed, we need to create a new file
789 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 988 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
790 m_inventoryFileNameSerial = m_inventorySerial; 989 m_inventoryFileNameSerial = m_inventorySerial;
791
792 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
793
794 lock (m_items)
795 {
796 foreach (TaskInventoryItem item in m_items.Values)
797 {
798 UUID ownerID = item.OwnerID;
799 uint everyoneMask = 0;
800 uint baseMask = item.BasePermissions;
801 uint ownerMask = item.CurrentPermissions;
802 uint groupMask = item.GroupPermissions;
803
804 invString.AddItemStart();
805 invString.AddNameValueLine("item_id", item.ItemID.ToString());
806 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
807
808 invString.AddPermissionsStart();
809
810 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
811 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
812 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
813 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
814 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
815
816 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
817 invString.AddNameValueLine("owner_id", ownerID.ToString());
818
819 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
820
821 invString.AddNameValueLine("group_id", item.GroupID.ToString());
822 invString.AddSectionEnd();
823
824 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
825 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
826 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
827 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
828
829 invString.AddSaleStart();
830 invString.AddNameValueLine("sale_type", "not");
831 invString.AddNameValueLine("sale_price", "0");
832 invString.AddSectionEnd();
833
834 invString.AddNameValueLine("name", item.Name + "|");
835 invString.AddNameValueLine("desc", item.Description + "|");
836
837 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
838 invString.AddSectionEnd();
839 }
840 }
841
842 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
843
844 return true; 990 return true;
845 } 991 }
846 992
847 // No need to recreate, the existing file is fine
848 return false; 993 return false;
849 } 994 }
850 995
@@ -854,26 +999,99 @@ namespace OpenSim.Region.Framework.Scenes
854 /// <param name="xferManager"></param> 999 /// <param name="xferManager"></param>
855 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 1000 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
856 { 1001 {
857 CreateInventoryFile(); 1002 bool changed = CreateInventoryFileName();
1003
1004 bool includeAssets = false;
1005 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1006 includeAssets = true;
1007
1008 if (m_inventoryPrivileged != includeAssets)
1009 changed = true;
1010
1011 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1012
1013 Items.LockItemsForRead(true);
858 1014
859 if (m_inventorySerial == 0) // No inventory 1015 if (m_inventorySerial == 0) // No inventory
860 { 1016 {
861 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1017 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1018 Items.LockItemsForRead(false);
862 return; 1019 return;
863 } 1020 }
864 1021
865 // In principle, we should only do the rest if the inventory changed; 1022 if (!changed)
866 // by sending m_inventorySerial to the client, it ought to know 1023 {
867 // that nothing changed and that it doesn't need to request the file. 1024 if (m_inventoryFileData.Length > 2)
868 // Unfortunately, it doesn't look like the client optimizes this; 1025 {
869 // the client seems to always come back and request the Xfer, 1026 xferManager.AddNewFile(m_inventoryFileName,
870 // no matter what value m_inventorySerial has. 1027 m_inventoryFileData);
1028 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1029 Util.StringToBytes256(m_inventoryFileName));
1030
1031 Items.LockItemsForRead(false);
1032 return;
1033 }
1034 }
1035
1036 m_inventoryPrivileged = includeAssets;
1037
1038 foreach (TaskInventoryItem item in m_items.Values)
1039 {
1040 UUID ownerID = item.OwnerID;
1041 uint everyoneMask = 0;
1042 uint baseMask = item.BasePermissions;
1043 uint ownerMask = item.CurrentPermissions;
1044 uint groupMask = item.GroupPermissions;
1045
1046 invString.AddItemStart();
1047 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1048 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1049
1050 invString.AddPermissionsStart();
1051
1052 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1053 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1054 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1055 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1056 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1057
1058 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1059 invString.AddNameValueLine("owner_id", ownerID.ToString());
1060
1061 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1062
1063 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1064 invString.AddSectionEnd();
1065
1066 if (includeAssets)
1067 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1068 else
1069 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1070 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
1071 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
1072 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1073
1074 invString.AddSaleStart();
1075 invString.AddNameValueLine("sale_type", "not");
1076 invString.AddNameValueLine("sale_price", "0");
1077 invString.AddSectionEnd();
1078
1079 invString.AddNameValueLine("name", item.Name + "|");
1080 invString.AddNameValueLine("desc", item.Description + "|");
1081
1082 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1083 invString.AddSectionEnd();
1084 }
1085
1086 Items.LockItemsForRead(false);
1087
1088 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
871 1089
872 if (m_inventoryFileData.Length > 2) 1090 if (m_inventoryFileData.Length > 2)
873 // Add the file for Xfer 1091 {
874 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 1092 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1093 }
875 1094
876 // Tell the client we're ready to Xfer the file
877 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, 1095 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
878 Util.StringToBytes256(m_inventoryFileName)); 1096 Util.StringToBytes256(m_inventoryFileName));
879 } 1097 }
@@ -886,10 +1104,11 @@ namespace OpenSim.Region.Framework.Scenes
886 { 1104 {
887 if (HasInventoryChanged) 1105 if (HasInventoryChanged)
888 { 1106 {
889 HasInventoryChanged = false; 1107 Items.LockItemsForRead(true);
890 List<TaskInventoryItem> items = GetInventoryItems(); 1108 datastore.StorePrimInventory(m_part.UUID, Items.Values);
891 datastore.StorePrimInventory(m_part.UUID, items); 1109 Items.LockItemsForRead(false);
892 1110
1111 HasInventoryChanged = false;
893 } 1112 }
894 } 1113 }
895 1114
@@ -956,82 +1175,63 @@ namespace OpenSim.Region.Framework.Scenes
956 { 1175 {
957 uint mask=0x7fffffff; 1176 uint mask=0x7fffffff;
958 1177
959 lock (m_items) 1178 foreach (TaskInventoryItem item in m_items.Values)
960 { 1179 {
961 foreach (TaskInventoryItem item in m_items.Values) 1180 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1181 mask &= ~((uint)PermissionMask.Copy >> 13);
1182 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1183 mask &= ~((uint)PermissionMask.Transfer >> 13);
1184 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1185 mask &= ~((uint)PermissionMask.Modify >> 13);
1186
1187 if (item.InvType == (int)InventoryType.Object)
962 { 1188 {
963 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1189 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
964 mask &= ~((uint)PermissionMask.Copy >> 13); 1190 mask &= ~((uint)PermissionMask.Copy >> 13);
965 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1191 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
966 mask &= ~((uint)PermissionMask.Transfer >> 13); 1192 mask &= ~((uint)PermissionMask.Transfer >> 13);
967 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1193 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
968 mask &= ~((uint)PermissionMask.Modify >> 13); 1194 mask &= ~((uint)PermissionMask.Modify >> 13);
969
970 if (item.InvType != (int)InventoryType.Object)
971 {
972 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
973 mask &= ~((uint)PermissionMask.Copy >> 13);
974 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
975 mask &= ~((uint)PermissionMask.Transfer >> 13);
976 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
977 mask &= ~((uint)PermissionMask.Modify >> 13);
978 }
979 else
980 {
981 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
982 mask &= ~((uint)PermissionMask.Copy >> 13);
983 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
984 mask &= ~((uint)PermissionMask.Transfer >> 13);
985 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
986 mask &= ~((uint)PermissionMask.Modify >> 13);
987 }
988
989 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
990 mask &= ~(uint)PermissionMask.Copy;
991 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
992 mask &= ~(uint)PermissionMask.Transfer;
993 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
994 mask &= ~(uint)PermissionMask.Modify;
995 } 1195 }
1196
1197 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1198 mask &= ~(uint)PermissionMask.Copy;
1199 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1200 mask &= ~(uint)PermissionMask.Transfer;
1201 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1202 mask &= ~(uint)PermissionMask.Modify;
996 } 1203 }
997
998 return mask; 1204 return mask;
999 } 1205 }
1000 1206
1001 public void ApplyNextOwnerPermissions() 1207 public void ApplyNextOwnerPermissions()
1002 { 1208 {
1003 lock (m_items) 1209 foreach (TaskInventoryItem item in m_items.Values)
1004 { 1210 {
1005 foreach (TaskInventoryItem item in m_items.Values) 1211 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1006 { 1212 {
1007 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1213 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1008 { 1214 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1009 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1215 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1010 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1216 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1011 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1217 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1012 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1218 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1013 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1014 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1015 }
1016 item.CurrentPermissions &= item.NextPermissions;
1017 item.BasePermissions &= item.NextPermissions;
1018 item.EveryonePermissions &= item.NextPermissions;
1019 item.OwnerChanged = true;
1020 item.PermsMask = 0;
1021 item.PermsGranter = UUID.Zero;
1022 } 1219 }
1220 item.OwnerChanged = true;
1221 item.CurrentPermissions &= item.NextPermissions;
1222 item.BasePermissions &= item.NextPermissions;
1223 item.EveryonePermissions &= item.NextPermissions;
1224 item.PermsMask = 0;
1225 item.PermsGranter = UUID.Zero;
1023 } 1226 }
1024 } 1227 }
1025 1228
1026 public void ApplyGodPermissions(uint perms) 1229 public void ApplyGodPermissions(uint perms)
1027 { 1230 {
1028 lock (m_items) 1231 foreach (TaskInventoryItem item in m_items.Values)
1029 { 1232 {
1030 foreach (TaskInventoryItem item in m_items.Values) 1233 item.CurrentPermissions = perms;
1031 { 1234 item.BasePermissions = perms;
1032 item.CurrentPermissions = perms;
1033 item.BasePermissions = perms;
1034 }
1035 } 1235 }
1036 m_inventorySerial++; 1236 m_inventorySerial++;
1037 HasInventoryChanged = true; 1237 HasInventoryChanged = true;
@@ -1039,17 +1239,13 @@ namespace OpenSim.Region.Framework.Scenes
1039 1239
1040 public bool ContainsScripts() 1240 public bool ContainsScripts()
1041 { 1241 {
1042 lock (m_items) 1242 foreach (TaskInventoryItem item in m_items.Values)
1043 { 1243 {
1044 foreach (TaskInventoryItem item in m_items.Values) 1244 if (item.InvType == (int)InventoryType.LSL)
1045 { 1245 {
1046 if (item.InvType == (int)InventoryType.LSL) 1246 return true;
1047 {
1048 return true;
1049 }
1050 } 1247 }
1051 } 1248 }
1052
1053 return false; 1249 return false;
1054 } 1250 }
1055 1251
@@ -1057,11 +1253,8 @@ namespace OpenSim.Region.Framework.Scenes
1057 { 1253 {
1058 List<UUID> ret = new List<UUID>(); 1254 List<UUID> ret = new List<UUID>();
1059 1255
1060 lock (m_items) 1256 foreach (TaskInventoryItem item in m_items.Values)
1061 { 1257 ret.Add(item.ItemID);
1062 foreach (TaskInventoryItem item in m_items.Values)
1063 ret.Add(item.ItemID);
1064 }
1065 1258
1066 return ret; 1259 return ret;
1067 } 1260 }
@@ -1092,6 +1285,11 @@ namespace OpenSim.Region.Framework.Scenes
1092 1285
1093 public Dictionary<UUID, string> GetScriptStates() 1286 public Dictionary<UUID, string> GetScriptStates()
1094 { 1287 {
1288 return GetScriptStates(false);
1289 }
1290
1291 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1292 {
1095 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1293 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1096 1294
1097 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1295 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1102,25 +1300,35 @@ namespace OpenSim.Region.Framework.Scenes
1102 if (engines == null) // No engine at all 1300 if (engines == null) // No engine at all
1103 return ret; 1301 return ret;
1104 1302
1105 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1303 Items.LockItemsForRead(true);
1106 1304 foreach (TaskInventoryItem item in m_items.Values)
1107 foreach (TaskInventoryItem item in scripts)
1108 { 1305 {
1109 foreach (IScriptModule e in engines) 1306 if (item.InvType == (int)InventoryType.LSL)
1110 { 1307 {
1111 if (e != null) 1308 foreach (IScriptModule e in engines)
1112 { 1309 {
1113 string n = e.GetXMLState(item.ItemID); 1310 if (e != null)
1114 if (n != String.Empty)
1115 { 1311 {
1116 if (!ret.ContainsKey(item.ItemID)) 1312 string n = e.GetXMLState(item.ItemID);
1117 ret[item.ItemID] = n; 1313 if (n != String.Empty)
1118 break; 1314 {
1315 if (oldIDs)
1316 {
1317 if (!ret.ContainsKey(item.OldItemID))
1318 ret[item.OldItemID] = n;
1319 }
1320 else
1321 {
1322 if (!ret.ContainsKey(item.ItemID))
1323 ret[item.ItemID] = n;
1324 }
1325 break;
1326 }
1119 } 1327 }
1120 } 1328 }
1121 } 1329 }
1122 } 1330 }
1123 1331 Items.LockItemsForRead(false);
1124 return ret; 1332 return ret;
1125 } 1333 }
1126 1334
@@ -1130,21 +1338,27 @@ namespace OpenSim.Region.Framework.Scenes
1130 if (engines == null) 1338 if (engines == null)
1131 return; 1339 return;
1132 1340
1133 List<TaskInventoryItem> scripts = GetInventoryScripts();
1134 1341
1135 foreach (TaskInventoryItem item in scripts) 1342 Items.LockItemsForRead(true);
1343
1344 foreach (TaskInventoryItem item in m_items.Values)
1136 { 1345 {
1137 foreach (IScriptModule engine in engines) 1346 if (item.InvType == (int)InventoryType.LSL)
1138 { 1347 {
1139 if (engine != null) 1348 foreach (IScriptModule engine in engines)
1140 { 1349 {
1141 if (item.OwnerChanged) 1350 if (engine != null)
1142 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1351 {
1143 item.OwnerChanged = false; 1352 if (item.OwnerChanged)
1144 engine.ResumeScript(item.ItemID); 1353 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1354 item.OwnerChanged = false;
1355 engine.ResumeScript(item.ItemID);
1356 }
1145 } 1357 }
1146 } 1358 }
1147 } 1359 }
1360
1361 Items.LockItemsForRead(false);
1148 } 1362 }
1149 } 1363 }
1150} 1364}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1aac09d..cdf8366 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>();
@@ -119,10 +123,12 @@ namespace OpenSim.Region.Framework.Scenes
119 private SceneObjectGroup proxyObjectGroup; 123 private SceneObjectGroup proxyObjectGroup;
120 //private SceneObjectPart proxyObjectPart = null; 124 //private SceneObjectPart proxyObjectPart = null;
121 public Vector3 lastKnownAllowedPosition; 125 public Vector3 lastKnownAllowedPosition;
122 public bool sentMessageAboutRestrictedParcelFlyingDown;
123 public Vector4 CollisionPlane = Vector4.UnitW; 126 public Vector4 CollisionPlane = Vector4.UnitW;
124 127
128 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
129 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
125 private Vector3 m_lastPosition; 130 private Vector3 m_lastPosition;
131 private Vector3 m_lastWorldPosition;
126 private Quaternion m_lastRotation; 132 private Quaternion m_lastRotation;
127 private Vector3 m_lastVelocity; 133 private Vector3 m_lastVelocity;
128 //private int m_lastTerseSent; 134 //private int m_lastTerseSent;
@@ -130,6 +136,11 @@ namespace OpenSim.Region.Framework.Scenes
130 private bool m_updateflag; 136 private bool m_updateflag;
131 private byte m_movementflag; 137 private byte m_movementflag;
132 private Vector3? m_forceToApply; 138 private Vector3? m_forceToApply;
139 private int m_userFlags;
140 public int UserFlags
141 {
142 get { return m_userFlags; }
143 }
133 private TeleportFlags m_teleportFlags; 144 private TeleportFlags m_teleportFlags;
134 public TeleportFlags TeleportFlags 145 public TeleportFlags TeleportFlags
135 { 146 {
@@ -160,9 +171,10 @@ namespace OpenSim.Region.Framework.Scenes
160 private int m_perfMonMS; 171 private int m_perfMonMS;
161 172
162 private bool m_setAlwaysRun; 173 private bool m_setAlwaysRun;
163
164 private bool m_forceFly; 174 private bool m_forceFly;
165 private bool m_flyDisabled; 175 private bool m_flyDisabled;
176 private bool m_flyingOld; // add for fly velocity control
177 public bool m_wasFlying; // add for fly velocity control
166 178
167 private float m_speedModifier = 1.0f; 179 private float m_speedModifier = 1.0f;
168 180
@@ -181,7 +193,8 @@ namespace OpenSim.Region.Framework.Scenes
181 protected RegionInfo m_regionInfo; 193 protected RegionInfo m_regionInfo;
182 protected ulong crossingFromRegion; 194 protected ulong crossingFromRegion;
183 195
184 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 196 private readonly Vector3[] Dir_Vectors = new Vector3[11];
197 private bool m_isNudging = false;
185 198
186 // Position of agent's camera in world (region cordinates) 199 // Position of agent's camera in world (region cordinates)
187 protected Vector3 m_CameraCenter; 200 protected Vector3 m_CameraCenter;
@@ -206,17 +219,25 @@ namespace OpenSim.Region.Framework.Scenes
206 private bool m_autopilotMoving; 219 private bool m_autopilotMoving;
207 private Vector3 m_autoPilotTarget; 220 private Vector3 m_autoPilotTarget;
208 private bool m_sitAtAutoTarget; 221 private bool m_sitAtAutoTarget;
222 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
209 223
210 private string m_nextSitAnimation = String.Empty; 224 private string m_nextSitAnimation = String.Empty;
211 225
212 //PauPaw:Proper PID Controler for autopilot************ 226 //PauPaw:Proper PID Controler for autopilot************
213 private bool m_moveToPositionInProgress; 227 private bool m_moveToPositionInProgress;
214 private Vector3 m_moveToPositionTarget; 228 private Vector3 m_moveToPositionTarget;
229 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
215 230
216 private bool m_followCamAuto; 231 private bool m_followCamAuto;
217 232
218 private int m_movementUpdateCount; 233 private int m_movementUpdateCount;
234 private int m_lastColCount = -1; //KF: Look for Collision chnages
235 private int m_updateCount = 0; //KF: Update Anims for a while
236 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
219 private const int NumMovementsBetweenRayCast = 5; 237 private const int NumMovementsBetweenRayCast = 5;
238 private List<uint> m_lastColliders = new List<uint>();
239
240 private object m_syncRoot = new Object();
220 241
221 private bool CameraConstraintActive; 242 private bool CameraConstraintActive;
222 //private int m_moveToPositionStateStatus; 243 //private int m_moveToPositionStateStatus;
@@ -243,7 +264,9 @@ namespace OpenSim.Region.Framework.Scenes
243 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 264 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
244 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 265 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
245 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 266 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, 267 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
268 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
269 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 270 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
248 } 271 }
249 272
@@ -450,7 +473,8 @@ namespace OpenSim.Region.Framework.Scenes
450 get 473 get
451 { 474 {
452 PhysicsActor actor = m_physicsActor; 475 PhysicsActor actor = m_physicsActor;
453 if (actor != null) 476// if (actor != null)
477 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
454 m_pos = actor.Position; 478 m_pos = actor.Position;
455 else 479 else
456 { 480 {
@@ -472,7 +496,7 @@ namespace OpenSim.Region.Framework.Scenes
472 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 496 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
473 if (part != null) 497 if (part != null)
474 { 498 {
475 return m_parentPosition + (m_pos * part.GetWorldRotation()); 499 return part.AbsolutePosition + (m_pos * part.GetWorldRotation());
476 } 500 }
477 else 501 else
478 { 502 {
@@ -499,7 +523,8 @@ namespace OpenSim.Region.Framework.Scenes
499 } 523 }
500 } 524 }
501 525
502 m_pos = value; 526 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
527 m_pos = value;
503 m_parentPosition = Vector3.Zero; 528 m_parentPosition = Vector3.Zero;
504 } 529 }
505 } 530 }
@@ -543,10 +568,39 @@ namespace OpenSim.Region.Framework.Scenes
543 } 568 }
544 } 569 }
545 570
571 public Quaternion OffsetRotation
572 {
573 get { return m_offsetRotation; }
574 set { m_offsetRotation = value; }
575 }
576
546 public Quaternion Rotation 577 public Quaternion Rotation
547 { 578 {
548 get { return m_bodyRot; } 579 get {
549 set { m_bodyRot = value; } 580 if (m_parentID != 0)
581 {
582 if (m_offsetRotation != null)
583 {
584 return m_offsetRotation;
585 }
586 else
587 {
588 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
589 }
590
591 }
592 else
593 {
594 return m_bodyRot;
595 }
596 }
597 set {
598 m_bodyRot = value;
599 if (m_parentID != 0)
600 {
601 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
602 }
603 }
550 } 604 }
551 605
552 public Quaternion PreviousRotation 606 public Quaternion PreviousRotation
@@ -571,11 +625,21 @@ namespace OpenSim.Region.Framework.Scenes
571 625
572 private uint m_parentID; 626 private uint m_parentID;
573 627
628
629 private UUID m_linkedPrim;
630
574 public uint ParentID 631 public uint ParentID
575 { 632 {
576 get { return m_parentID; } 633 get { return m_parentID; }
577 set { m_parentID = value; } 634 set { m_parentID = value; }
578 } 635 }
636
637 public UUID LinkedPrim
638 {
639 get { return m_linkedPrim; }
640 set { m_linkedPrim = value; }
641 }
642
579 public float Health 643 public float Health
580 { 644 {
581 get { return m_health; } 645 get { return m_health; }
@@ -697,7 +761,7 @@ namespace OpenSim.Region.Framework.Scenes
697 CreateSceneViewer(); 761 CreateSceneViewer();
698 m_animator = new ScenePresenceAnimator(this); 762 m_animator = new ScenePresenceAnimator(this);
699 } 763 }
700 764
701 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 765 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
702 { 766 {
703 m_DrawDistance = world.DefaultDrawDistance; 767 m_DrawDistance = world.DefaultDrawDistance;
@@ -712,6 +776,7 @@ namespace OpenSim.Region.Framework.Scenes
712 m_localId = m_scene.AllocateLocalId(); 776 m_localId = m_scene.AllocateLocalId();
713 777
714 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;
715 780
716 if (account != null) 781 if (account != null)
717 m_userLevel = account.UserLevel; 782 m_userLevel = account.UserLevel;
@@ -730,10 +795,7 @@ namespace OpenSim.Region.Framework.Scenes
730 m_reprioritization_timer.AutoReset = false; 795 m_reprioritization_timer.AutoReset = false;
731 796
732 AdjustKnownSeeds(); 797 AdjustKnownSeeds();
733
734 // TODO: I think, this won't send anything, as we are still a child here...
735 Animator.TrySetMovementAnimation("STAND"); 798 Animator.TrySetMovementAnimation("STAND");
736
737 // 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.
738 // Request info about all the (root) agents in this region 800 // Request info about all the (root) agents in this region
739 // 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)
@@ -784,25 +846,47 @@ namespace OpenSim.Region.Framework.Scenes
784 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 846 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
785 Dir_Vectors[4] = Vector3.UnitZ; //UP 847 Dir_Vectors[4] = Vector3.UnitZ; //UP
786 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 848 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
787 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 849 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
788 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 850 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
789 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
790 } 854 }
791 855
792 private Vector3[] GetWalkDirectionVectors() 856 private Vector3[] GetWalkDirectionVectors()
793 { 857 {
794 Vector3[] vector = new Vector3[9]; 858 Vector3[] vector = new Vector3[11];
795 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
796 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
797 vector[2] = Vector3.UnitY; //LEFT 861 vector[2] = Vector3.UnitY; //LEFT
798 vector[3] = -Vector3.UnitY; //RIGHT 862 vector[3] = -Vector3.UnitY; //RIGHT
799 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
800 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
801 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
802 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
803 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
804 return vector; 870 return vector;
805 } 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
806 890
807 #endregion 891 #endregion
808 892
@@ -867,6 +951,62 @@ namespace OpenSim.Region.Framework.Scenes
867 pos.Y = crossedBorder.BorderLine.Z - 1; 951 pos.Y = crossedBorder.BorderLine.Z - 1;
868 } 952 }
869 953
954 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
955 if (land != null)
956 {
957 // If we come in via login, landmark or map, we want to
958 // honor landing points. If we come in via Lure, we want
959 // to ignore them.
960 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
961 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ||
962 (m_teleportFlags & TeleportFlags.ViaLocation) != 0)
963 {
964 // Don't restrict gods, estate managers, or land owners to
965 // the TP point. This behaviour mimics agni.
966 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
967 land.LandData.UserLocation != Vector3.Zero &&
968 GodLevel < 200 &&
969 ((land.LandData.OwnerID != m_uuid &&
970 (!m_scene.Permissions.IsGod(m_uuid)) &&
971 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0))
972 {
973 pos = land.LandData.UserLocation;
974 }
975 }
976
977 land.SendLandUpdateToClient(ControllingClient);
978 }
979
980 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
981 {
982 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
983
984 if (pos.X < 0)
985 {
986 emergencyPos.X = (int)Constants.RegionSize + pos.X;
987 if (!(pos.Y < 0))
988 emergencyPos.Y = pos.Y;
989 if (!(pos.Z < 0))
990 emergencyPos.Z = pos.Z;
991 }
992 if (pos.Y < 0)
993 {
994 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
995 if (!(pos.X < 0))
996 emergencyPos.X = pos.X;
997 if (!(pos.Z < 0))
998 emergencyPos.Z = pos.Z;
999 }
1000 if (pos.Z < 0)
1001 {
1002 emergencyPos.Z = 128;
1003 if (!(pos.Y < 0))
1004 emergencyPos.Y = pos.Y;
1005 if (!(pos.X < 0))
1006 emergencyPos.X = pos.X;
1007 }
1008 }
1009
870 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1010 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
871 { 1011 {
872 m_log.WarnFormat( 1012 m_log.WarnFormat(
@@ -1012,16 +1152,21 @@ namespace OpenSim.Region.Framework.Scenes
1012 /// <summary> 1152 /// <summary>
1013 /// Removes physics plugin scene representation of this agent if it exists. 1153 /// Removes physics plugin scene representation of this agent if it exists.
1014 /// </summary> 1154 /// </summary>
1015 private void RemoveFromPhysicalScene() 1155 public void RemoveFromPhysicalScene()
1016 { 1156 {
1017 if (PhysicsActor != null) 1157 if (PhysicsActor != null)
1018 { 1158 {
1019 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1159 try
1020 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1160 {
1021 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1161 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1022 m_physicsActor.UnSubscribeEvents(); 1162 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
1023 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1163 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1024 PhysicsActor = null; 1164 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1165 m_physicsActor.UnSubscribeEvents();
1166 PhysicsActor = null;
1167 }
1168 catch
1169 { }
1025 } 1170 }
1026 } 1171 }
1027 1172
@@ -1032,11 +1177,13 @@ namespace OpenSim.Region.Framework.Scenes
1032 public void Teleport(Vector3 pos) 1177 public void Teleport(Vector3 pos)
1033 { 1178 {
1034 bool isFlying = false; 1179 bool isFlying = false;
1180
1035 if (m_physicsActor != null) 1181 if (m_physicsActor != null)
1036 isFlying = m_physicsActor.Flying; 1182 isFlying = m_physicsActor.Flying;
1037 1183
1038 RemoveFromPhysicalScene(); 1184 RemoveFromPhysicalScene();
1039 Velocity = Vector3.Zero; 1185 Velocity = Vector3.Zero;
1186 CheckLandingPoint(ref pos);
1040 AbsolutePosition = pos; 1187 AbsolutePosition = pos;
1041 AddToPhysicalScene(isFlying); 1188 AddToPhysicalScene(isFlying);
1042 if (m_appearance != null) 1189 if (m_appearance != null)
@@ -1046,6 +1193,7 @@ namespace OpenSim.Region.Framework.Scenes
1046 } 1193 }
1047 1194
1048 SendTerseUpdateToAllClients(); 1195 SendTerseUpdateToAllClients();
1196
1049 } 1197 }
1050 1198
1051 public void TeleportWithMomentum(Vector3 pos) 1199 public void TeleportWithMomentum(Vector3 pos)
@@ -1055,6 +1203,7 @@ namespace OpenSim.Region.Framework.Scenes
1055 isFlying = m_physicsActor.Flying; 1203 isFlying = m_physicsActor.Flying;
1056 1204
1057 RemoveFromPhysicalScene(); 1205 RemoveFromPhysicalScene();
1206 CheckLandingPoint(ref pos);
1058 AbsolutePosition = pos; 1207 AbsolutePosition = pos;
1059 AddToPhysicalScene(isFlying); 1208 AddToPhysicalScene(isFlying);
1060 if (m_appearance != null) 1209 if (m_appearance != null)
@@ -1265,6 +1414,7 @@ namespace OpenSim.Region.Framework.Scenes
1265 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1414 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1266 1415
1267 m_pos = m_LastFinitePos; 1416 m_pos = m_LastFinitePos;
1417
1268 if (!m_pos.IsFinite()) 1418 if (!m_pos.IsFinite())
1269 { 1419 {
1270 m_pos.X = 127f; 1420 m_pos.X = 127f;
@@ -1335,7 +1485,6 @@ namespace OpenSim.Region.Framework.Scenes
1335 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1485 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1336 } 1486 }
1337 } 1487 }
1338
1339 lock (scriptedcontrols) 1488 lock (scriptedcontrols)
1340 { 1489 {
1341 if (scriptedcontrols.Count > 0) 1490 if (scriptedcontrols.Count > 0)
@@ -1350,6 +1499,9 @@ namespace OpenSim.Region.Framework.Scenes
1350 1499
1351 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1500 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1352 { 1501 {
1502 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1503 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1504
1353 // TODO: This doesn't prevent the user from walking yet. 1505 // TODO: This doesn't prevent the user from walking yet.
1354 // Setting parent ID would fix this, if we knew what value 1506 // Setting parent ID would fix this, if we knew what value
1355 // to use. Or we could add a m_isSitting variable. 1507 // to use. Or we could add a m_isSitting variable.
@@ -1398,12 +1550,20 @@ namespace OpenSim.Region.Framework.Scenes
1398 if (actor.Flying != oldflying) 1550 if (actor.Flying != oldflying)
1399 update_movementflag = true; 1551 update_movementflag = true;
1400 1552
1553 if (m_animator.m_jumping) // add for jumping
1554 update_movementflag = true;
1555
1401 if (q != m_bodyRot) 1556 if (q != m_bodyRot)
1402 { 1557 {
1403 m_bodyRot = q; 1558 m_bodyRot = q;
1404 update_rotation = true; 1559 update_rotation = true;
1405 } 1560 }
1406 1561
1562 //guilty until proven innocent..
1563 bool Nudging = true;
1564 //Basically, if there is at least one non-nudge control then we don't need
1565 //to worry about stopping the avatar
1566
1407 if (m_parentID == 0) 1567 if (m_parentID == 0)
1408 { 1568 {
1409 bool bAllowUpdateMoveToPosition = false; 1569 bool bAllowUpdateMoveToPosition = false;
@@ -1418,9 +1578,12 @@ namespace OpenSim.Region.Framework.Scenes
1418 else 1578 else
1419 dirVectors = Dir_Vectors; 1579 dirVectors = Dir_Vectors;
1420 1580
1421 // The fact that m_movementflag is a byte needs to be fixed 1581 bool[] isNudge = GetDirectionIsNudge();
1422 // it really should be a uint 1582
1423 uint nudgehack = 250; 1583
1584
1585
1586
1424 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1587 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1425 { 1588 {
1426 if (((uint)flags & (uint)DCF) != 0) 1589 if (((uint)flags & (uint)DCF) != 0)
@@ -1430,40 +1593,28 @@ namespace OpenSim.Region.Framework.Scenes
1430 try 1593 try
1431 { 1594 {
1432 agent_control_v3 += dirVectors[i]; 1595 agent_control_v3 += dirVectors[i];
1433 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1596 if (isNudge[i] == false)
1597 {
1598 Nudging = false;
1599 }
1434 } 1600 }
1435 catch (IndexOutOfRangeException) 1601 catch (IndexOutOfRangeException)
1436 { 1602 {
1437 // Why did I get this? 1603 // Why did I get this?
1438 } 1604 }
1439 1605
1440 if ((m_movementflag & (byte)(uint)DCF) == 0) 1606 if ((m_movementflag & (uint)DCF) == 0)
1441 { 1607 {
1442 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1443 {
1444 m_movementflag |= (byte)nudgehack;
1445 }
1446 m_movementflag += (byte)(uint)DCF; 1608 m_movementflag += (byte)(uint)DCF;
1447 update_movementflag = true; 1609 update_movementflag = true;
1448 } 1610 }
1449 } 1611 }
1450 else 1612 else
1451 { 1613 {
1452 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1614 if ((m_movementflag & (uint)DCF) != 0)
1453 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1454 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1455 ) // This or is for Nudge forward
1456 { 1615 {
1457 m_movementflag -= ((byte)(uint)DCF); 1616 m_movementflag -= (byte)(uint)DCF;
1458
1459 update_movementflag = true; 1617 update_movementflag = true;
1460 /*
1461 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1462 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1463 {
1464 m_log.Debug("Removed Hack flag");
1465 }
1466 */
1467 } 1618 }
1468 else 1619 else
1469 { 1620 {
@@ -1472,7 +1623,6 @@ namespace OpenSim.Region.Framework.Scenes
1472 } 1623 }
1473 i++; 1624 i++;
1474 } 1625 }
1475
1476 //Paupaw:Do Proper PID for Autopilot here 1626 //Paupaw:Do Proper PID for Autopilot here
1477 if (bResetMoveToPosition) 1627 if (bResetMoveToPosition)
1478 { 1628 {
@@ -1484,8 +1634,41 @@ namespace OpenSim.Region.Framework.Scenes
1484 1634
1485 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) 1635 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
1486 { 1636 {
1637/*
1638 bool twoD = false;
1639 bool there = false;
1640 if (Animator != null)
1641 {
1642 switch (Animator.CurrentMovementAnimation)
1643 {
1644 case "STAND":
1645 case "WALK":
1646 case "RUN":
1647 case "CROUCH":
1648 case "CROUCHWALK":
1649 {
1650 twoD = true;
1651 }
1652 break;
1653 }
1654 }
1655
1656 if (twoD)
1657 {
1658*/
1659 Vector3 abspos = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, 0.0f);
1660 Vector3 tgt = new Vector3(m_moveToPositionTarget.X, m_moveToPositionTarget.Y, 0.0f);
1661/* if (Util.GetDistanceTo(abspos, tgt) <= 0.5f) there = true;
1662 }
1663 else
1664 {
1665 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) there = true;
1666 }
1667*/
1487 //Check the error term of the current position in relation to the target position 1668 //Check the error term of the current position in relation to the target position
1488 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) 1669// if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
1670// if (there)
1671 if (Util.GetDistanceTo(abspos, tgt) <= 0.5f)
1489 { 1672 {
1490 // we are close enough to the target 1673 // we are close enough to the target
1491 m_moveToPositionTarget = Vector3.Zero; 1674 m_moveToPositionTarget = Vector3.Zero;
@@ -1502,11 +1685,15 @@ namespace OpenSim.Region.Framework.Scenes
1502 // unknown forces are acting on the avatar and we need to adaptively respond 1685 // unknown forces are acting on the avatar and we need to adaptively respond
1503 // to such forces, but the following simple approach seems to works fine. 1686 // to such forces, but the following simple approach seems to works fine.
1504 Vector3 LocalVectorToTarget3D = 1687 Vector3 LocalVectorToTarget3D =
1505 (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 1688// (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
1689 (tgt - abspos)
1506 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords 1690 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
1507 // Ignore z component of vector 1691 // Ignore z component of vector
1508 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1692 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1509 LocalVectorToTarget2D.Normalize(); 1693 LocalVectorToTarget2D.Normalize();
1694
1695 //We're not nudging
1696 Nudging = false;
1510 agent_control_v3 += LocalVectorToTarget2D; 1697 agent_control_v3 += LocalVectorToTarget2D;
1511 1698
1512 // update avatar movement flags. the avatar coordinate system is as follows: 1699 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1597,13 +1784,13 @@ namespace OpenSim.Region.Framework.Scenes
1597 // m_log.DebugFormat( 1784 // m_log.DebugFormat(
1598 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1785 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1599 1786
1600 AddNewMovement(agent_control_v3, q); 1787 AddNewMovement(agent_control_v3, q, Nudging);
1601 1788
1602 1789
1603 } 1790 }
1604 } 1791 }
1605 1792
1606 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1793 if (update_movementflag && !SitGround)
1607 Animator.UpdateMovementAnimations(); 1794 Animator.UpdateMovementAnimations();
1608 1795
1609 m_scene.EventManager.TriggerOnClientMovement(this); 1796 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1618,7 +1805,6 @@ namespace OpenSim.Region.Framework.Scenes
1618 m_sitAtAutoTarget = false; 1805 m_sitAtAutoTarget = false;
1619 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1806 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1620 //proxy.PCode = (byte)PCode.ParticleSystem; 1807 //proxy.PCode = (byte)PCode.ParticleSystem;
1621
1622 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1808 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1623 proxyObjectGroup.AttachToScene(m_scene); 1809 proxyObjectGroup.AttachToScene(m_scene);
1624 1810
@@ -1637,8 +1823,15 @@ namespace OpenSim.Region.Framework.Scenes
1637// } 1823// }
1638 } 1824 }
1639 1825
1826 public void StopMoveToPosition()
1827 {
1828 m_moveToPositionTarget = Vector3.Zero;
1829 m_moveToPositionInProgress = false;
1830 }
1831
1640 public void DoMoveToPosition(Object sender, string method, List<String> args) 1832 public void DoMoveToPosition(Object sender, string method, List<String> args)
1641 { 1833 {
1834//Console.WriteLine("SP:DoMoveToPosition");
1642 try 1835 try
1643 { 1836 {
1644 float locx = 0f; 1837 float locx = 0f;
@@ -1660,7 +1853,7 @@ namespace OpenSim.Region.Framework.Scenes
1660 } 1853 }
1661 m_moveToPositionInProgress = true; 1854 m_moveToPositionInProgress = true;
1662 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1855 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1663 } 1856 }
1664 catch (Exception ex) 1857 catch (Exception ex)
1665 { 1858 {
1666 //Why did I get this error? 1859 //Why did I get this error?
@@ -1682,7 +1875,7 @@ namespace OpenSim.Region.Framework.Scenes
1682 Velocity = Vector3.Zero; 1875 Velocity = Vector3.Zero;
1683 SendAvatarDataToAllAgents(); 1876 SendAvatarDataToAllAgents();
1684 1877
1685 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1878 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1686 } 1879 }
1687 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1880 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1688 m_requestedSitTargetUUID = UUID.Zero; 1881 m_requestedSitTargetUUID = UUID.Zero;
@@ -1719,25 +1912,22 @@ namespace OpenSim.Region.Framework.Scenes
1719 1912
1720 if (m_parentID != 0) 1913 if (m_parentID != 0)
1721 { 1914 {
1722 m_log.Debug("StandupCode Executed"); 1915 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1723 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1724 if (part != null) 1916 if (part != null)
1725 { 1917 {
1918 part.TaskInventory.LockItemsForRead(true);
1726 TaskInventoryDictionary taskIDict = part.TaskInventory; 1919 TaskInventoryDictionary taskIDict = part.TaskInventory;
1727 if (taskIDict != null) 1920 if (taskIDict != null)
1728 { 1921 {
1729 lock (taskIDict) 1922 foreach (UUID taskID in taskIDict.Keys)
1730 { 1923 {
1731 foreach (UUID taskID in taskIDict.Keys) 1924 UnRegisterControlEventsToScript(LocalId, taskID);
1732 { 1925 taskIDict[taskID].PermsMask &= ~(
1733 UnRegisterControlEventsToScript(LocalId, taskID); 1926 2048 | //PERMISSION_CONTROL_CAMERA
1734 taskIDict[taskID].PermsMask &= ~( 1927 4); // PERMISSION_TAKE_CONTROLS
1735 2048 | //PERMISSION_CONTROL_CAMERA
1736 4); // PERMISSION_TAKE_CONTROLS
1737 }
1738 } 1928 }
1739
1740 } 1929 }
1930 part.TaskInventory.LockItemsForRead(false);
1741 // Reset sit target. 1931 // Reset sit target.
1742 if (part.GetAvatarOnSitTarget() == UUID) 1932 if (part.GetAvatarOnSitTarget() == UUID)
1743 part.SitTargetAvatar = UUID.Zero; 1933 part.SitTargetAvatar = UUID.Zero;
@@ -1746,16 +1936,55 @@ namespace OpenSim.Region.Framework.Scenes
1746 m_parentPosition = part.GetWorldPosition(); 1936 m_parentPosition = part.GetWorldPosition();
1747 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1937 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1748 } 1938 }
1939 // part.GetWorldRotation() is the rotation of the object being sat on
1940 // Rotation is the sittiing Av's rotation
1941
1942 Quaternion partRot;
1943// if (part.LinkNum == 1)
1944// { // Root prim of linkset
1945// partRot = part.ParentGroup.RootPart.RotationOffset;
1946// }
1947// else
1948// { // single or child prim
1949
1950// }
1951 if (part == null) //CW: Part may be gone. llDie() for example.
1952 {
1953 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1954 }
1955 else
1956 {
1957 partRot = part.GetWorldRotation();
1958 }
1749 1959
1960 Quaternion partIRot = Quaternion.Inverse(partRot);
1961
1962 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1963 Vector3 avStandUp = new Vector3(0.3f, 0f, 0f) * avatarRot; // 0.3M infront of av
1964
1965
1750 if (m_physicsActor == null) 1966 if (m_physicsActor == null)
1751 { 1967 {
1752 AddToPhysicalScene(false); 1968 AddToPhysicalScene(false);
1753 } 1969 }
1754 1970 //CW: If the part isn't null then we can set the current position
1755 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1971 if (part != null)
1756 m_parentPosition = Vector3.Zero; 1972 {
1757 1973 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1758 m_parentID = 0; 1974 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1975 part.IsOccupied = false;
1976 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1977 }
1978 else
1979 {
1980 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1981 AbsolutePosition = m_lastWorldPosition;
1982 }
1983
1984 m_parentPosition = Vector3.Zero;
1985 m_parentID = 0;
1986 m_linkedPrim = UUID.Zero;
1987 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1759 SendAvatarDataToAllAgents(); 1988 SendAvatarDataToAllAgents();
1760 m_requestedSitTargetID = 0; 1989 m_requestedSitTargetID = 0;
1761 if (m_physicsActor != null && m_appearance != null) 1990 if (m_physicsActor != null && m_appearance != null)
@@ -1764,7 +1993,6 @@ namespace OpenSim.Region.Framework.Scenes
1764 SetHeight(m_appearance.AvatarHeight); 1993 SetHeight(m_appearance.AvatarHeight);
1765 } 1994 }
1766 } 1995 }
1767
1768 Animator.TrySetMovementAnimation("STAND"); 1996 Animator.TrySetMovementAnimation("STAND");
1769 } 1997 }
1770 1998
@@ -1795,13 +2023,9 @@ namespace OpenSim.Region.Framework.Scenes
1795 Vector3 avSitOffSet = part.SitTargetPosition; 2023 Vector3 avSitOffSet = part.SitTargetPosition;
1796 Quaternion avSitOrientation = part.SitTargetOrientation; 2024 Quaternion avSitOrientation = part.SitTargetOrientation;
1797 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2025 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1798 2026 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1799 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2027 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1800 bool SitTargetisSet = 2028 if (SitTargetisSet && !SitTargetOccupied)
1801 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1802 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1803
1804 if (SitTargetisSet && SitTargetUnOccupied)
1805 { 2029 {
1806 //switch the target to this prim 2030 //switch the target to this prim
1807 return part; 2031 return part;
@@ -1815,85 +2039,168 @@ namespace OpenSim.Region.Framework.Scenes
1815 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 2039 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1816 { 2040 {
1817 bool autopilot = true; 2041 bool autopilot = true;
2042 Vector3 autopilotTarget = new Vector3();
2043 Quaternion sitOrientation = Quaternion.Identity;
1818 Vector3 pos = new Vector3(); 2044 Vector3 pos = new Vector3();
1819 Quaternion sitOrientation = pSitOrientation;
1820 Vector3 cameraEyeOffset = Vector3.Zero; 2045 Vector3 cameraEyeOffset = Vector3.Zero;
1821 Vector3 cameraAtOffset = Vector3.Zero; 2046 Vector3 cameraAtOffset = Vector3.Zero;
1822 bool forceMouselook = false; 2047 bool forceMouselook = false;
1823 2048
1824 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 2049 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1825 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 2050 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1826 if (part != null) 2051 if (part == null) return;
1827 { 2052
1828 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 2053 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1829 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 2054 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1830 2055
1831 // Is a sit target available? 2056 // part is the prim to sit on
1832 Vector3 avSitOffSet = part.SitTargetPosition; 2057 // offset is the world-ref vector distance from that prim center to the click-spot
1833 Quaternion avSitOrientation = part.SitTargetOrientation; 2058 // UUID is the UUID of the Avatar doing the clicking
1834 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2059
1835 2060 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1836 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2061
1837 bool SitTargetisSet = 2062 // Is a sit target available?
1838 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 2063 Vector3 avSitOffSet = part.SitTargetPosition;
1839 ( 2064 Quaternion avSitOrientation = part.SitTargetOrientation;
1840 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 2065
1841 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 2066 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1842 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 2067 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1843 ) 2068 Quaternion partRot;
1844 )); 2069// if (part.LinkNum == 1)
1845 2070// { // Root prim of linkset
1846 if (SitTargetisSet && SitTargetUnOccupied) 2071// partRot = part.ParentGroup.RootPart.RotationOffset;
1847 { 2072// }
1848 part.SitTargetAvatar = UUID; 2073// else
1849 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 2074// { // single or child prim
1850 sitOrientation = avSitOrientation; 2075 partRot = part.GetWorldRotation();
1851 autopilot = false; 2076// }
1852 } 2077 Quaternion partIRot = Quaternion.Inverse(partRot);
1853 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2078//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1854 2079 // Sit analysis rewritten by KF 091125
1855 pos = part.AbsolutePosition + offset; 2080 if (SitTargetisSet) // scipted sit
1856 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 2081 {
1857 //{ 2082 if (!part.IsOccupied)
1858 // offset = pos; 2083 {
1859 //autopilot = false; 2084//Console.WriteLine("Scripted, unoccupied");
1860 //} 2085 part.SitTargetAvatar = UUID; // set that Av will be on it
1861 if (m_physicsActor != null) 2086 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1862 { 2087
1863 // If we're not using the client autopilot, we're immediately warping the avatar to the location 2088 Quaternion nrot = avSitOrientation;
1864 // We can remove the physicsActor until they stand up. 2089 if (!part.IsRoot)
1865 m_sitAvatarHeight = m_physicsActor.Size.Z;
1866
1867 if (autopilot)
1868 { 2090 {
1869 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 2091 nrot = part.RotationOffset * avSitOrientation;
1870 {
1871 autopilot = false;
1872
1873 RemoveFromPhysicalScene();
1874 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1875 }
1876 } 2092 }
1877 else 2093 sitOrientation = nrot; // Change rotatione to the scripted one
2094 OffsetRotation = nrot;
2095 autopilot = false; // Jump direct to scripted llSitPos()
2096 }
2097 else
2098 {
2099//Console.WriteLine("Scripted, occupied");
2100 return;
2101 }
2102 }
2103 else // Not Scripted
2104 {
2105 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
2106 {
2107 // large prim & offset, ignore if other Avs sitting
2108// offset.Z -= 0.05f;
2109 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
2110 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
2111
2112//Console.WriteLine(" offset ={0}", offset);
2113//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
2114//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
2115
2116 }
2117 else // small offset
2118 {
2119//Console.WriteLine("Small offset");
2120 if (!part.IsOccupied)
2121 {
2122 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2123 autopilotTarget = part.AbsolutePosition;
2124//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2125 }
2126 else return; // occupied small
2127 } // end large/small
2128 } // end Scripted/not
2129
2130 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2131
2132 cameraAtOffset = part.GetCameraAtOffset();
2133 cameraEyeOffset = part.GetCameraEyeOffset();
2134 forceMouselook = part.GetForceMouselook();
2135 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2136 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2137
2138 if (m_physicsActor != null)
2139 {
2140 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2141 // We can remove the physicsActor until they stand up.
2142 m_sitAvatarHeight = m_physicsActor.Size.Z;
2143 if (autopilot)
2144 { // its not a scripted sit
2145// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2146 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1878 { 2147 {
2148 autopilot = false; // close enough
2149 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2150 Not using the part's position because returning the AV to the last known standing
2151 position is likely to be more friendly, isn't it? */
1879 RemoveFromPhysicalScene(); 2152 RemoveFromPhysicalScene();
1880 } 2153 Velocity = Vector3.Zero;
2154 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2155 } // else the autopilot will get us close
2156 }
2157 else
2158 { // its a scripted sit
2159 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2160 I *am* using the part's position this time because we have no real idea how far away
2161 the avatar is from the sit target. */
2162 RemoveFromPhysicalScene();
2163 Velocity = Vector3.Zero;
1881 } 2164 }
1882
1883 cameraAtOffset = part.GetCameraAtOffset();
1884 cameraEyeOffset = part.GetCameraEyeOffset();
1885 forceMouselook = part.GetForceMouselook();
1886 } 2165 }
1887 2166 else return; // physactor is null!
1888 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2167
1889 m_requestedSitTargetUUID = targetID; 2168 Vector3 offsetr; // = offset * partIRot;
2169 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2170 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2171 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2172 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2173 //offsetr = offset * partIRot;
2174//
2175 // }
2176 // else
2177 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2178 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2179 // (offset * partRot);
2180 // }
2181
2182//Console.WriteLine(" ");
2183//Console.WriteLine("link number ={0}", part.LinkNum);
2184//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2185//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2186//Console.WriteLine("Click offst ={0}", offset);
2187//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2188//Console.WriteLine("offsetr ={0}", offsetr);
2189//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2190//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2191
2192 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2193 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2194
2195 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1890 // This calls HandleAgentSit twice, once from here, and the client calls 2196 // This calls HandleAgentSit twice, once from here, and the client calls
1891 // HandleAgentSit itself after it gets to the location 2197 // HandleAgentSit itself after it gets to the location
1892 // It doesn't get to the location until we've moved them there though 2198 // It doesn't get to the location until we've moved them there though
1893 // which happens in HandleAgentSit :P 2199 // which happens in HandleAgentSit :P
1894 m_autopilotMoving = autopilot; 2200 m_autopilotMoving = autopilot;
1895 m_autoPilotTarget = pos; 2201 m_autoPilotTarget = autopilotTarget;
1896 m_sitAtAutoTarget = autopilot; 2202 m_sitAtAutoTarget = autopilot;
2203 m_initialSitTarget = autopilotTarget;
1897 if (!autopilot) 2204 if (!autopilot)
1898 HandleAgentSit(remoteClient, UUID); 2205 HandleAgentSit(remoteClient, UUID);
1899 } 2206 }
@@ -2188,47 +2495,130 @@ namespace OpenSim.Region.Framework.Scenes
2188 { 2495 {
2189 if (part != null) 2496 if (part != null)
2190 { 2497 {
2498//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2191 if (part.GetAvatarOnSitTarget() == UUID) 2499 if (part.GetAvatarOnSitTarget() == UUID)
2192 { 2500 {
2501//Console.WriteLine("Scripted Sit");
2502 // Scripted sit
2193 Vector3 sitTargetPos = part.SitTargetPosition; 2503 Vector3 sitTargetPos = part.SitTargetPosition;
2194 Quaternion sitTargetOrient = part.SitTargetOrientation; 2504 Quaternion sitTargetOrient = part.SitTargetOrientation;
2195
2196 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2197 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2198
2199 //Quaternion result = (sitTargetOrient * vq) * nq;
2200
2201 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2505 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2202 m_pos += SIT_TARGET_ADJUSTMENT; 2506 m_pos += SIT_TARGET_ADJUSTMENT;
2507 if (!part.IsRoot)
2508 {
2509 m_pos *= part.RotationOffset;
2510 }
2203 m_bodyRot = sitTargetOrient; 2511 m_bodyRot = sitTargetOrient;
2204 //Rotation = sitTargetOrient;
2205 m_parentPosition = part.AbsolutePosition; 2512 m_parentPosition = part.AbsolutePosition;
2206 2513 part.IsOccupied = true;
2207 //SendTerseUpdateToAllClients(); 2514 part.ParentGroup.AddAvatar(agentID);
2208 } 2515 }
2209 else 2516 else
2210 { 2517 {
2211 m_pos -= part.AbsolutePosition; 2518 // if m_avUnscriptedSitPos is zero then Av sits above center
2519 // Else Av sits at m_avUnscriptedSitPos
2520
2521 // Non-scripted sit by Kitto Flora 21Nov09
2522 // Calculate angle of line from prim to Av
2523 Quaternion partIRot;
2524// if (part.LinkNum == 1)
2525// { // Root prim of linkset
2526// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2527// }
2528// else
2529// { // single or child prim
2530 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2531// }
2532 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2533 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2534 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2535 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2536 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2537 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2538 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2539 // Av sits at world euler <0,0, z>, translated by part rotation
2540 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2541
2212 m_parentPosition = part.AbsolutePosition; 2542 m_parentPosition = part.AbsolutePosition;
2213 } 2543 part.IsOccupied = true;
2544 part.ParentGroup.AddAvatar(agentID);
2545 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2546 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2547 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2548 m_avUnscriptedSitPos; // adds click offset, if any
2549 //Set up raytrace to find top surface of prim
2550 Vector3 size = part.Scale;
2551 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2552 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2553 Vector3 down = new Vector3(0f, 0f, -1f);
2554//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2555 m_scene.PhysicsScene.RaycastWorld(
2556 start, // Vector3 position,
2557 down, // Vector3 direction,
2558 mag, // float length,
2559 SitAltitudeCallback); // retMethod
2560 } // end scripted/not
2214 } 2561 }
2215 else 2562 else // no Av
2216 { 2563 {
2217 return; 2564 return;
2218 } 2565 }
2219 } 2566 }
2220 m_parentID = m_requestedSitTargetID;
2221 2567
2568 //We want our offsets to reference the root prim, not the child we may have sat on
2569 if (!part.IsRoot)
2570 {
2571 m_parentID = part.ParentGroup.RootPart.LocalId;
2572 m_pos += part.OffsetPosition;
2573 }
2574 else
2575 {
2576 m_parentID = m_requestedSitTargetID;
2577 }
2578
2579 m_linkedPrim = part.UUID;
2580 if (part.GetAvatarOnSitTarget() != UUID)
2581 {
2582 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2583 }
2222 Velocity = Vector3.Zero; 2584 Velocity = Vector3.Zero;
2223 RemoveFromPhysicalScene(); 2585 RemoveFromPhysicalScene();
2224
2225 Animator.TrySetMovementAnimation(sitAnimation); 2586 Animator.TrySetMovementAnimation(sitAnimation);
2226 SendAvatarDataToAllAgents(); 2587 SendAvatarDataToAllAgents();
2227 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2228 // So we're also sending a terse update (which has avatar rotation)
2229 // [Update] We do now.
2230 //SendTerseUpdateToAllClients(); 2588 //SendTerseUpdateToAllClients();
2231 } 2589 }
2590
2591 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2592 {
2593 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2594 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2595 if(hitYN)
2596 {
2597 // m_pos = Av offset from prim center to make look like on center
2598 // m_parentPosition = Actual center pos of prim
2599 // collisionPoint = spot on prim where we want to sit
2600 // collisionPoint.Z = global sit surface height
2601 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2602 Quaternion partIRot;
2603// if (part.LinkNum == 1)
2604/// { // Root prim of linkset
2605// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2606// }
2607// else
2608// { // single or child prim
2609 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2610// }
2611 if (m_initialSitTarget != null)
2612 {
2613 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2614 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2615 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2616 m_pos += offset;
2617 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2618 }
2619
2620 }
2621 } // End SitAltitudeCallback KF.
2232 2622
2233 /// <summary> 2623 /// <summary>
2234 /// Event handler for the 'Always run' setting on the client 2624 /// Event handler for the 'Always run' setting on the client
@@ -2258,12 +2648,13 @@ namespace OpenSim.Region.Framework.Scenes
2258 /// </summary> 2648 /// </summary>
2259 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2649 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2260 /// <param name="rotation">The direction in which this avatar should now face. 2650 /// <param name="rotation">The direction in which this avatar should now face.
2261 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2651 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2262 { 2652 {
2263 if (m_isChildAgent) 2653 if (m_isChildAgent)
2264 { 2654 {
2265 // WHAT??? 2655 // WHAT???
2266 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); 2656 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent");
2657
2267 return; 2658 return;
2268 } 2659 }
2269 2660
@@ -2272,15 +2663,26 @@ namespace OpenSim.Region.Framework.Scenes
2272 Rotation = rotation; 2663 Rotation = rotation;
2273 Vector3 direc = vec * rotation; 2664 Vector3 direc = vec * rotation;
2274 direc.Normalize(); 2665 direc.Normalize();
2666 PhysicsActor actor = m_physicsActor;
2667
2668 if (actor.Flying != m_flyingOld) // add for fly velocity control
2669 {
2670 m_flyingOld = actor.Flying; // add for fly velocity control
2671 if (!actor.Flying) m_wasFlying = true; // add for fly velocity control
2672 }
2673
2674 if (m_physicsActor.IsColliding == true) m_wasFlying = false; // add for fly velocity control
2675
2676 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2275 2677
2276 direc *= 0.03f * 128f * m_speedModifier; 2678 direc *= 0.03f * 128f * m_speedModifier;
2277 2679
2278 PhysicsActor actor = m_physicsActor;
2279 if (actor != null) 2680 if (actor != null)
2280 { 2681 {
2281 if (actor.Flying) 2682 if (actor.Flying)
2282 { 2683 {
2283 direc *= 4.0f; 2684// rm speed mod direc *= 4.0f;
2685 direc *= 5.2f; // for speed mod
2284 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2686 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2285 //bool colliding = (m_physicsActor.IsColliding==true); 2687 //bool colliding = (m_physicsActor.IsColliding==true);
2286 //if (controlland) 2688 //if (controlland)
@@ -2293,22 +2695,34 @@ namespace OpenSim.Region.Framework.Scenes
2293 // m_log.Info("[AGENT]: Stop FLying"); 2695 // m_log.Info("[AGENT]: Stop FLying");
2294 //} 2696 //}
2295 } 2697 }
2698 if (Animator.m_falling && m_wasFlying) // if falling from flying, disable motion add
2699 {
2700 direc *= 0.0f;
2701 }
2702 /* This jumping section removed to SPA
2296 else if (!actor.Flying && actor.IsColliding) 2703 else if (!actor.Flying && actor.IsColliding)
2297 { 2704 {
2298 if (direc.Z > 2.0f) 2705 if (direc.Z > 2.0f)
2299 { 2706 {
2300 direc.Z *= 3.0f; 2707 if(m_animator.m_animTickJump == -1)
2301 2708 {
2302 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2709 direc.Z *= 3.0f; // jump
2303 Animator.TrySetMovementAnimation("PREJUMP"); 2710 }
2304 Animator.TrySetMovementAnimation("JUMP"); 2711 else
2712 {
2713 direc.Z *= 0.1f; // prejump
2714 }
2715 / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2716 Animator.TrySetMovementAnimation("PREJUMP");
2717 Animator.TrySetMovementAnimation("JUMP");
2718 * /
2305 } 2719 }
2306 } 2720 } */
2307 } 2721 }
2308 2722
2309 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2723 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2310 m_forceToApply = direc; 2724 m_forceToApply = direc;
2311 2725 m_isNudging = Nudging;
2312 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2726 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2313 } 2727 }
2314 2728
@@ -2357,6 +2771,9 @@ namespace OpenSim.Region.Framework.Scenes
2357 2771
2358 CheckForSignificantMovement(); // sends update to the modules. 2772 CheckForSignificantMovement(); // sends update to the modules.
2359 } 2773 }
2774
2775 //Sending prim updates AFTER the avatar terse updates are sent
2776 SendPrimUpdates();
2360 } 2777 }
2361 2778
2362 #endregion 2779 #endregion
@@ -3149,6 +3566,7 @@ namespace OpenSim.Region.Framework.Scenes
3149 m_callbackURI = cAgent.CallbackURI; 3566 m_callbackURI = cAgent.CallbackURI;
3150 3567
3151 m_pos = cAgent.Position; 3568 m_pos = cAgent.Position;
3569
3152 m_velocity = cAgent.Velocity; 3570 m_velocity = cAgent.Velocity;
3153 m_CameraCenter = cAgent.Center; 3571 m_CameraCenter = cAgent.Center;
3154 m_CameraAtAxis = cAgent.AtAxis; 3572 m_CameraAtAxis = cAgent.AtAxis;
@@ -3237,17 +3655,45 @@ namespace OpenSim.Region.Framework.Scenes
3237 /// </summary> 3655 /// </summary>
3238 public override void UpdateMovement() 3656 public override void UpdateMovement()
3239 { 3657 {
3240 if (m_forceToApply.HasValue) 3658 if (Animator!=null) // add for jumping
3241 { 3659 { // add for jumping
3242 Vector3 force = m_forceToApply.Value; 3660 // if (!m_animator.m_jumping) // add for jumping
3243 3661 // { // add for jumping
3244 m_updateflag = true;
3245 3662
3246 Velocity = force; 3663 if (m_forceToApply.HasValue) // this section realigned
3664 {
3247 3665
3248 m_forceToApply = null; 3666 Vector3 force = m_forceToApply.Value;
3249 } 3667 m_updateflag = true;
3250 } 3668if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3669 Velocity = force;
3670//Console.WriteLine("UM1 {0}", Velocity);
3671 m_forceToApply = null;
3672 }
3673 else
3674 {
3675 if (m_isNudging)
3676 {
3677 Vector3 force = Vector3.Zero;
3678
3679 m_updateflag = true;
3680if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3681 Velocity = force;
3682//Console.WriteLine("UM2 {0}", Velocity);
3683 m_isNudging = false;
3684 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3685 }
3686 else // add for jumping
3687 { // add for jumping
3688 Vector3 force = Vector3.Zero; // add for jumping
3689if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3690//Console.WriteLine("UM3 {0}", Velocity);
3691 Velocity = force; // add for jumping
3692 }
3693 }
3694 // } // end realign
3695 } // add for jumping
3696 } // add for jumping
3251 3697
3252 /// <summary> 3698 /// <summary>
3253 /// Adds a physical representation of the avatar to the Physics plugin 3699 /// Adds a physical representation of the avatar to the Physics plugin
@@ -3261,10 +3707,8 @@ namespace OpenSim.Region.Framework.Scenes
3261 3707
3262 Vector3 pVec = AbsolutePosition; 3708 Vector3 pVec = AbsolutePosition;
3263 3709
3264 // Old bug where the height was in centimeters instead of meters
3265 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, 3710 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3266 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3711 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3267
3268 scene.AddPhysicsActorTaint(m_physicsActor); 3712 scene.AddPhysicsActorTaint(m_physicsActor);
3269 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3713 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3270 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3714 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3288,18 +3732,29 @@ namespace OpenSim.Region.Framework.Scenes
3288 { 3732 {
3289 if (e == null) 3733 if (e == null)
3290 return; 3734 return;
3291 3735
3292 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3736 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3293 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3294 // as of this comment the interval is set in AddToPhysicalScene 3737 // as of this comment the interval is set in AddToPhysicalScene
3295 if (Animator!=null) 3738 if (Animator!=null)
3296 Animator.UpdateMovementAnimations(); 3739 {
3740 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3741 { // else its will lock out other animation changes, like ground sit.
3742 Animator.UpdateMovementAnimations();
3743 m_updateCount--;
3744 }
3745 }
3297 3746
3298 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3747 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3299 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3748 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3300 3749
3301 CollisionPlane = Vector4.UnitW; 3750 CollisionPlane = Vector4.UnitW;
3302 3751
3752 if (m_lastColCount != coldata.Count)
3753 {
3754 m_updateCount = UPDATE_COUNT;
3755 m_lastColCount = coldata.Count;
3756 }
3757
3303 if (coldata.Count != 0 && Animator != null) 3758 if (coldata.Count != 0 && Animator != null)
3304 { 3759 {
3305 switch (Animator.CurrentMovementAnimation) 3760 switch (Animator.CurrentMovementAnimation)
@@ -3329,6 +3784,148 @@ namespace OpenSim.Region.Framework.Scenes
3329 } 3784 }
3330 } 3785 }
3331 3786
3787 List<uint> thisHitColliders = new List<uint>();
3788 List<uint> endedColliders = new List<uint>();
3789 List<uint> startedColliders = new List<uint>();
3790
3791 foreach (uint localid in coldata.Keys)
3792 {
3793 thisHitColliders.Add(localid);
3794 if (!m_lastColliders.Contains(localid))
3795 {
3796 startedColliders.Add(localid);
3797 }
3798 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3799 }
3800
3801 // calculate things that ended colliding
3802 foreach (uint localID in m_lastColliders)
3803 {
3804 if (!thisHitColliders.Contains(localID))
3805 {
3806 endedColliders.Add(localID);
3807 }
3808 }
3809 //add the items that started colliding this time to the last colliders list.
3810 foreach (uint localID in startedColliders)
3811 {
3812 m_lastColliders.Add(localID);
3813 }
3814 // remove things that ended colliding from the last colliders list
3815 foreach (uint localID in endedColliders)
3816 {
3817 m_lastColliders.Remove(localID);
3818 }
3819
3820 // do event notification
3821 if (startedColliders.Count > 0)
3822 {
3823 ColliderArgs StartCollidingMessage = new ColliderArgs();
3824 List<DetectedObject> colliding = new List<DetectedObject>();
3825 foreach (uint localId in startedColliders)
3826 {
3827 if (localId == 0)
3828 continue;
3829
3830 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3831 string data = "";
3832 if (obj != null)
3833 {
3834 DetectedObject detobj = new DetectedObject();
3835 detobj.keyUUID = obj.UUID;
3836 detobj.nameStr = obj.Name;
3837 detobj.ownerUUID = obj.OwnerID;
3838 detobj.posVector = obj.AbsolutePosition;
3839 detobj.rotQuat = obj.GetWorldRotation();
3840 detobj.velVector = obj.Velocity;
3841 detobj.colliderType = 0;
3842 detobj.groupUUID = obj.GroupID;
3843 colliding.Add(detobj);
3844 }
3845 }
3846
3847 if (colliding.Count > 0)
3848 {
3849 StartCollidingMessage.Colliders = colliding;
3850
3851 foreach (SceneObjectGroup att in Attachments)
3852 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3853 }
3854 }
3855
3856 if (endedColliders.Count > 0)
3857 {
3858 ColliderArgs EndCollidingMessage = new ColliderArgs();
3859 List<DetectedObject> colliding = new List<DetectedObject>();
3860 foreach (uint localId in endedColliders)
3861 {
3862 if (localId == 0)
3863 continue;
3864
3865 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3866 string data = "";
3867 if (obj != null)
3868 {
3869 DetectedObject detobj = new DetectedObject();
3870 detobj.keyUUID = obj.UUID;
3871 detobj.nameStr = obj.Name;
3872 detobj.ownerUUID = obj.OwnerID;
3873 detobj.posVector = obj.AbsolutePosition;
3874 detobj.rotQuat = obj.GetWorldRotation();
3875 detobj.velVector = obj.Velocity;
3876 detobj.colliderType = 0;
3877 detobj.groupUUID = obj.GroupID;
3878 colliding.Add(detobj);
3879 }
3880 }
3881
3882 if (colliding.Count > 0)
3883 {
3884 EndCollidingMessage.Colliders = colliding;
3885
3886 foreach (SceneObjectGroup att in Attachments)
3887 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3888 }
3889 }
3890
3891 if (thisHitColliders.Count > 0)
3892 {
3893 ColliderArgs CollidingMessage = new ColliderArgs();
3894 List<DetectedObject> colliding = new List<DetectedObject>();
3895 foreach (uint localId in thisHitColliders)
3896 {
3897 if (localId == 0)
3898 continue;
3899
3900 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3901 string data = "";
3902 if (obj != null)
3903 {
3904 DetectedObject detobj = new DetectedObject();
3905 detobj.keyUUID = obj.UUID;
3906 detobj.nameStr = obj.Name;
3907 detobj.ownerUUID = obj.OwnerID;
3908 detobj.posVector = obj.AbsolutePosition;
3909 detobj.rotQuat = obj.GetWorldRotation();
3910 detobj.velVector = obj.Velocity;
3911 detobj.colliderType = 0;
3912 detobj.groupUUID = obj.GroupID;
3913 colliding.Add(detobj);
3914 }
3915 }
3916
3917 if (colliding.Count > 0)
3918 {
3919 CollidingMessage.Colliders = colliding;
3920
3921 lock (m_attachments)
3922 {
3923 foreach (SceneObjectGroup att in m_attachments)
3924 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3925 }
3926 }
3927 }
3928
3332 if (m_invulnerable) 3929 if (m_invulnerable)
3333 return; 3930 return;
3334 3931
@@ -3413,6 +4010,10 @@ namespace OpenSim.Region.Framework.Scenes
3413 { 4010 {
3414 lock (m_attachments) 4011 lock (m_attachments)
3415 { 4012 {
4013 // This may be true when the attachment comes back
4014 // from serialization after login. Clear it.
4015 gobj.IsDeleted = false;
4016
3416 m_attachments.Add(gobj); 4017 m_attachments.Add(gobj);
3417 } 4018 }
3418 } 4019 }
@@ -3754,6 +4355,39 @@ namespace OpenSim.Region.Framework.Scenes
3754 return; 4355 return;
3755 } 4356 }
3756 4357
4358 XmlDocument doc = new XmlDocument();
4359 string stateData = String.Empty;
4360
4361 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4362 if (attServ != null)
4363 {
4364 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4365 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4366 if (stateData != String.Empty)
4367 {
4368 try
4369 {
4370 doc.LoadXml(stateData);
4371 }
4372 catch { }
4373 }
4374 }
4375
4376 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4377
4378 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4379 if (nodes.Count > 0)
4380 {
4381 foreach (XmlNode n in nodes)
4382 {
4383 XmlElement elem = (XmlElement)n;
4384 string itemID = elem.GetAttribute("ItemID");
4385 string xml = elem.InnerXml;
4386
4387 itemData[new UUID(itemID)] = xml;
4388 }
4389 }
4390
3757 List<AvatarAttachment> attachments = m_appearance.GetAttachments(); 4391 List<AvatarAttachment> attachments = m_appearance.GetAttachments();
3758 foreach (AvatarAttachment attach in attachments) 4392 foreach (AvatarAttachment attach in attachments)
3759 { 4393 {
@@ -3774,7 +4408,30 @@ namespace OpenSim.Region.Framework.Scenes
3774 4408
3775 try 4409 try
3776 { 4410 {
3777 m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4411 string xmlData;
4412 XmlDocument d = new XmlDocument();
4413 UUID asset;
4414 if (itemData.TryGetValue(itemID, out xmlData))
4415 {
4416 d.LoadXml(xmlData);
4417 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4418
4419 // Rez from inventory
4420 asset
4421 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4422
4423 }
4424 else
4425 {
4426 // Rez from inventory (with a null doc to let
4427 // CHANGED_OWNER happen)
4428 asset
4429 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4430 }
4431
4432 m_log.InfoFormat(
4433 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}",
4434 p, itemID, asset);
3778 } 4435 }
3779 catch (Exception e) 4436 catch (Exception e)
3780 { 4437 {
@@ -3807,6 +4464,15 @@ namespace OpenSim.Region.Framework.Scenes
3807 m_reprioritization_called = false; 4464 m_reprioritization_called = false;
3808 } 4465 }
3809 } 4466 }
4467
4468 private Vector3 Quat2Euler(Quaternion rot){
4469 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4470 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4471 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4472 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4473 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4474 return(new Vector3(x,y,z));
4475 }
3810 4476
3811 public void SaveChangedAttachments() 4477 public void SaveChangedAttachments()
3812 { 4478 {
@@ -3830,5 +4496,30 @@ namespace OpenSim.Region.Framework.Scenes
3830 } 4496 }
3831 } 4497 }
3832 } 4498 }
4499
4500 private void CheckLandingPoint(ref Vector3 pos)
4501 {
4502 // Never constrain lures
4503 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
4504 return;
4505
4506 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
4507 return;
4508
4509 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
4510
4511 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
4512 land.LandData.UserLocation != Vector3.Zero &&
4513 land.LandData.OwnerID != m_uuid &&
4514 (!m_scene.Permissions.IsGod(m_uuid)) &&
4515 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)))
4516 {
4517 float curr = Vector3.Distance(AbsolutePosition, pos);
4518 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
4519 pos = land.LandData.UserLocation;
4520 else
4521 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
4522 }
4523 }
3833 } 4524 }
3834} 4525}
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 bb8a83a..769d8a5 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 }
@@ -237,7 +237,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
237 if (originalLinkNum != 0) 237 if (originalLinkNum != 0)
238 part.LinkNum = originalLinkNum; 238 part.LinkNum = originalLinkNum;
239 239
240 part.StoreUndoState(); 240 part.StoreUndoState(UndoType.STATE_ALL);
241 reader.Close(); 241 reader.Close();
242 sr.Close(); 242 sr.Close();
243 } 243 }
@@ -1458,12 +1458,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1458 { 1458 {
1459 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1459 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1460 1460
1461 if (reader.IsEmptyElement)
1462 {
1463 reader.Read();
1464 return tinv;
1465 }
1466
1467 reader.ReadStartElement(name, String.Empty); 1461 reader.ReadStartElement(name, String.Empty);
1468 1462
1469 while (reader.Name == "TaskInventoryItem") 1463 while (reader.Name == "TaskInventoryItem")
@@ -1497,12 +1491,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1497 { 1491 {
1498 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1492 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1499 1493
1500 if (reader.IsEmptyElement)
1501 {
1502 reader.Read();
1503 return shape;
1504 }
1505
1506 reader.ReadStartElement(name, String.Empty); // Shape 1494 reader.ReadStartElement(name, String.Empty); // Shape
1507 1495
1508 string nodeName = string.Empty; 1496 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 77b1535..fdfbc78 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;