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.cs4
-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.cs4
-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.cs708
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs309
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs759
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs1073
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs25
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs168
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
28 files changed, 3238 insertions, 1219 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 07e97d5..c38ecd9 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -40,11 +40,11 @@ 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 bool TeleportHome(UUID id, IClientAPI client);
44
43 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 45 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
44 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); 46 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq);
45 47
46 void TeleportHome(UUID id, IClientAPI client);
47
48 bool Cross(ScenePresence agent, bool isFlying); 48 bool Cross(ScenePresence agent, bool isFlying);
49 49
50 void AgentArrivedAtDestination(UUID agent); 50 void AgentArrivedAtDestination(UUID agent);
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 d9752e6..641e226 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -51,6 +51,8 @@ namespace OpenSim.Region.Framework.Interfaces
51 51
52 ArrayList GetScriptErrors(UUID itemID); 52 ArrayList GetScriptErrors(UUID itemID);
53 53
54 bool HasScript(UUID itemID, out bool running);
55
54 void SaveAllState(); 56 void SaveAllState();
55 } 57 }
56} 58}
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 b67937d..3ec4e59 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;
@@ -776,6 +780,26 @@ namespace OpenSim.Region.Framework.Scenes
776 } 780 }
777 } 781 }
778 } 782 }
783 public void TriggerTerrainUpdate()
784 {
785 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
786 if (handlerTerrainUpdate != null)
787 {
788 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
789 {
790 try
791 {
792 d();
793 }
794 catch (Exception e)
795 {
796 m_log.ErrorFormat(
797 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
798 e.Message, e.StackTrace);
799 }
800 }
801 }
802 }
779 803
780 public void TriggerTerrainTick() 804 public void TriggerTerrainTick()
781 { 805 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 4595a29..657df15 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -158,7 +158,7 @@ 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 uint pqueue = ComputeDistancePriority(client,entity,true); 161 uint pqueue = ComputeDistancePriority(client,entity,false);
162 162
163 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 163 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
164 if (presence != null) 164 if (presence != null)
@@ -228,7 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
228 228
229 for (int i = 0; i < queues - 1; i++) 229 for (int i = 0; i < queues - 1; i++)
230 { 230 {
231 if (distance < 10 * Math.Pow(2.0,i)) 231 if (distance < 30 * Math.Pow(2.0,i))
232 break; 232 break;
233 pqueue++; 233 pqueue++;
234 } 234 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 13085e3..28c0276 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))
@@ -706,6 +689,8 @@ namespace OpenSim.Region.Framework.Scenes
706 return; 689 return;
707 } 690 }
708 691
692 if (newName == null) newName = item.Name;
693
709 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 694 AssetBase asset = AssetService.Get(item.AssetID.ToString());
710 695
711 if (asset != null) 696 if (asset != null)
@@ -759,6 +744,24 @@ namespace OpenSim.Region.Framework.Scenes
759 } 744 }
760 745
761 /// <summary> 746 /// <summary>
747 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
748 /// </summary>
749 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
750 {
751 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
752 foreach (InventoryItemBase b in items)
753 {
754 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
755 InventoryItemBase n = InventoryService.GetItem(b);
756 n.Folder = destfolder;
757 moveitems.Add(n);
758 remoteClient.SendInventoryItemCreateUpdate(n, 0);
759 }
760
761 MoveInventoryItem(remoteClient, moveitems);
762 }
763
764 /// <summary>
762 /// Move an item within the agent's inventory. 765 /// Move an item within the agent's inventory.
763 /// </summary> 766 /// </summary>
764 /// <param name="remoteClient"></param> 767 /// <param name="remoteClient"></param>
@@ -959,8 +962,12 @@ namespace OpenSim.Region.Framework.Scenes
959 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 962 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
960 { 963 {
961 SceneObjectPart part = GetSceneObjectPart(localID); 964 SceneObjectPart part = GetSceneObjectPart(localID);
962 SceneObjectGroup group = part.ParentGroup; 965 SceneObjectGroup group = null;
963 if (group != null) 966 if (part != null)
967 {
968 group = part.ParentGroup;
969 }
970 if (part != null && group != null)
964 { 971 {
965 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 972 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
966 return; 973 return;
@@ -1196,6 +1203,10 @@ namespace OpenSim.Region.Framework.Scenes
1196 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1203 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1197 return; 1204 return;
1198 1205
1206 bool overrideNoMod = false;
1207 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1208 overrideNoMod = true;
1209
1199 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1210 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1200 { 1211 {
1201 // object cannot copy items to an object owned by a different owner 1212 // object cannot copy items to an object owned by a different owner
@@ -1205,7 +1216,7 @@ namespace OpenSim.Region.Framework.Scenes
1205 } 1216 }
1206 1217
1207 // must have both move and modify permission to put an item in an object 1218 // must have both move and modify permission to put an item in an object
1208 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1219 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1209 { 1220 {
1210 return; 1221 return;
1211 } 1222 }
@@ -1264,6 +1275,14 @@ namespace OpenSim.Region.Framework.Scenes
1264 1275
1265 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1276 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1266 { 1277 {
1278 SceneObjectPart destPart = GetSceneObjectPart(destID);
1279 if (destPart != null) // Move into a prim
1280 {
1281 foreach(UUID itemID in items)
1282 MoveTaskInventoryItem(destID, host, itemID);
1283 return destID; // Prim folder ID == prim ID
1284 }
1285
1267 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1286 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1268 1287
1269 UUID newFolderID = UUID.Random(); 1288 UUID newFolderID = UUID.Random();
@@ -1443,13 +1462,6 @@ namespace OpenSim.Region.Framework.Scenes
1443 { 1462 {
1444 agentTransactions.HandleTaskItemUpdateFromTransaction( 1463 agentTransactions.HandleTaskItemUpdateFromTransaction(
1445 remoteClient, part, transactionID, currentItem); 1464 remoteClient, part, transactionID, currentItem);
1446
1447 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1448 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1449 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1450 remoteClient.SendAgentAlertMessage("Script saved", false);
1451 else
1452 remoteClient.SendAgentAlertMessage("Item saved", false);
1453 } 1465 }
1454 1466
1455 // Base ALWAYS has move 1467 // Base ALWAYS has move
@@ -1590,7 +1602,7 @@ namespace OpenSim.Region.Framework.Scenes
1590 return; 1602 return;
1591 1603
1592 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1604 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1593 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1605 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1594 remoteClient.AgentId); 1606 remoteClient.AgentId);
1595 AssetService.Store(asset); 1607 AssetService.Store(asset);
1596 1608
@@ -1743,23 +1755,32 @@ namespace OpenSim.Region.Framework.Scenes
1743 // build a list of eligible objects 1755 // build a list of eligible objects
1744 List<uint> deleteIDs = new List<uint>(); 1756 List<uint> deleteIDs = new List<uint>();
1745 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1757 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1746 1758 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1747 // Start with true for both, then remove the flags if objects
1748 // that we can't derez are part of the selection
1749 bool permissionToTake = true;
1750 bool permissionToTakeCopy = true;
1751 bool permissionToDelete = true;
1752 1759
1753 foreach (uint localID in localIDs) 1760 foreach (uint localID in localIDs)
1754 { 1761 {
1762 // Start with true for both, then remove the flags if objects
1763 // that we can't derez are part of the selection
1764 bool permissionToTake = true;
1765 bool permissionToTakeCopy = true;
1766 bool permissionToDelete = true;
1767
1755 // Invalid id 1768 // Invalid id
1756 SceneObjectPart part = GetSceneObjectPart(localID); 1769 SceneObjectPart part = GetSceneObjectPart(localID);
1757 if (part == null) 1770 if (part == null)
1771 {
1772 //Client still thinks the object exists, kill it
1773 deleteIDs.Add(localID);
1758 continue; 1774 continue;
1775 }
1759 1776
1760 // Already deleted by someone else 1777 // Already deleted by someone else
1761 if (part.ParentGroup == null || part.ParentGroup.IsDeleted) 1778 if (part.ParentGroup == null || part.ParentGroup.IsDeleted)
1779 {
1780 //Client still thinks the object exists, kill it
1781 deleteIDs.Add(localID);
1762 continue; 1782 continue;
1783 }
1763 1784
1764 // Can't delete child prims 1785 // Can't delete child prims
1765 if (part != part.ParentGroup.RootPart) 1786 if (part != part.ParentGroup.RootPart)
@@ -1767,9 +1788,6 @@ namespace OpenSim.Region.Framework.Scenes
1767 1788
1768 SceneObjectGroup grp = part.ParentGroup; 1789 SceneObjectGroup grp = part.ParentGroup;
1769 1790
1770 deleteIDs.Add(localID);
1771 deleteGroups.Add(grp);
1772
1773 if (remoteClient == null) 1791 if (remoteClient == null)
1774 { 1792 {
1775 // Autoreturn has a null client. Nothing else does. So 1793 // Autoreturn has a null client. Nothing else does. So
@@ -1786,80 +1804,104 @@ namespace OpenSim.Region.Framework.Scenes
1786 } 1804 }
1787 else 1805 else
1788 { 1806 {
1789 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1807 if (action == DeRezAction.TakeCopy)
1808 {
1809 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1810 permissionToTakeCopy = false;
1811 }
1812 else
1813 {
1790 permissionToTakeCopy = false; 1814 permissionToTakeCopy = false;
1791 1815 }
1792 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1816 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1793 permissionToTake = false; 1817 permissionToTake = false;
1794 1818
1795 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1819 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1796 permissionToDelete = false; 1820 permissionToDelete = false;
1797 } 1821 }
1798 }
1799 1822
1800 // Handle god perms 1823 // Handle god perms
1801 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1824 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1802 { 1825 {
1803 permissionToTake = true; 1826 permissionToTake = true;
1804 permissionToTakeCopy = true; 1827 permissionToTakeCopy = true;
1805 permissionToDelete = true; 1828 permissionToDelete = true;
1806 } 1829 }
1807 1830
1808 // If we're re-saving, we don't even want to delete 1831 // If we're re-saving, we don't even want to delete
1809 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1832 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1810 permissionToDelete = false; 1833 permissionToDelete = false;
1811 1834
1812 // if we want to take a copy, we also don't want to delete 1835 // if we want to take a copy, we also don't want to delete
1813 // Note: after this point, the permissionToTakeCopy flag 1836 // Note: after this point, the permissionToTakeCopy flag
1814 // becomes irrelevant. It already includes the permissionToTake 1837 // becomes irrelevant. It already includes the permissionToTake
1815 // permission and after excluding no copy items here, we can 1838 // permission and after excluding no copy items here, we can
1816 // just use that. 1839 // just use that.
1817 if (action == DeRezAction.TakeCopy) 1840 if (action == DeRezAction.TakeCopy)
1818 { 1841 {
1819 // If we don't have permission, stop right here 1842 // If we don't have permission, stop right here
1820 if (!permissionToTakeCopy) 1843 if (!permissionToTakeCopy)
1821 return; 1844 return;
1822 1845
1823 permissionToTake = true; 1846 permissionToTake = true;
1824 // Don't delete 1847 // Don't delete
1825 permissionToDelete = false; 1848 permissionToDelete = false;
1826 } 1849 }
1827 1850
1828 if (action == DeRezAction.Return) 1851 if (action == DeRezAction.Return)
1829 {
1830 if (remoteClient != null)
1831 { 1852 {
1832 if (Permissions.CanReturnObjects( 1853 if (remoteClient != null)
1833 null,
1834 remoteClient.AgentId,
1835 deleteGroups))
1836 { 1854 {
1837 permissionToTake = true; 1855 if (Permissions.CanReturnObjects(
1838 permissionToDelete = true; 1856 null,
1839 1857 remoteClient.AgentId,
1840 foreach (SceneObjectGroup g in deleteGroups) 1858 deleteGroups))
1841 { 1859 {
1842 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1860 permissionToTake = true;
1861 permissionToDelete = true;
1862
1863 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1843 } 1864 }
1844 } 1865 }
1866 else // Auto return passes through here with null agent
1867 {
1868 permissionToTake = true;
1869 permissionToDelete = true;
1870 }
1845 } 1871 }
1846 else // Auto return passes through here with null agent 1872
1873 if (permissionToTake && (!permissionToDelete))
1874 takeGroups.Add(grp);
1875
1876 if (permissionToDelete)
1847 { 1877 {
1848 permissionToTake = true; 1878 if (permissionToTake)
1849 permissionToDelete = true; 1879 deleteGroups.Add(grp);
1880 deleteIDs.Add(grp.LocalId);
1850 } 1881 }
1851 } 1882 }
1852 1883
1853 if (permissionToTake) 1884 SendKillObject(deleteIDs);
1885
1886 if (deleteGroups.Count > 0)
1854 { 1887 {
1888 foreach (SceneObjectGroup g in deleteGroups)
1889 deleteIDs.Remove(g.LocalId);
1890
1855 m_asyncSceneObjectDeleter.DeleteToInventory( 1891 m_asyncSceneObjectDeleter.DeleteToInventory(
1856 action, destinationID, deleteGroups, remoteClient, 1892 action, destinationID, deleteGroups, remoteClient,
1857 permissionToDelete); 1893 true);
1894 }
1895 if (takeGroups.Count > 0)
1896 {
1897 m_asyncSceneObjectDeleter.DeleteToInventory(
1898 action, destinationID, takeGroups, remoteClient,
1899 false);
1858 } 1900 }
1859 else if (permissionToDelete) 1901 if (deleteIDs.Count > 0)
1860 { 1902 {
1861 foreach (SceneObjectGroup g in deleteGroups) 1903 foreach (SceneObjectGroup g in deleteGroups)
1862 DeleteSceneObject(g, false); 1904 DeleteSceneObject(g, true);
1863 } 1905 }
1864 } 1906 }
1865 1907
@@ -1911,21 +1953,29 @@ namespace OpenSim.Region.Framework.Scenes
1911 else // oopsies 1953 else // oopsies
1912 item.Folder = UUID.Zero; 1954 item.Folder = UUID.Zero;
1913 1955
1956 // Set up base perms properly
1957 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1958 permsBase &= grp.RootPart.BaseMask;
1959 permsBase |= (uint)PermissionMask.Move;
1960
1961 // Make sure we don't lock it
1962 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1963
1914 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions()) 1964 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1915 { 1965 {
1916 item.BasePermissions = grp.RootPart.NextOwnerMask; 1966 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1917 item.CurrentPermissions = grp.RootPart.NextOwnerMask; 1967 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1918 item.NextPermissions = grp.RootPart.NextOwnerMask; 1968 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1919 item.EveryOnePermissions = grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask; 1969 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1920 item.GroupPermissions = grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask; 1970 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1921 } 1971 }
1922 else 1972 else
1923 { 1973 {
1924 item.BasePermissions = grp.RootPart.BaseMask; 1974 item.BasePermissions = permsBase;
1925 item.CurrentPermissions = grp.RootPart.OwnerMask; 1975 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1926 item.NextPermissions = grp.RootPart.NextOwnerMask; 1976 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1927 item.EveryOnePermissions = grp.RootPart.EveryoneMask; 1977 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1928 item.GroupPermissions = grp.RootPart.GroupMask; 1978 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1929 } 1979 }
1930 item.CreationDate = Util.UnixTimeSinceEpoch(); 1980 item.CreationDate = Util.UnixTimeSinceEpoch();
1931 1981
@@ -2069,6 +2119,9 @@ namespace OpenSim.Region.Framework.Scenes
2069 2119
2070 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2120 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2071 { 2121 {
2122 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2123 return;
2124
2072 SceneObjectPart part = GetSceneObjectPart(objectID); 2125 SceneObjectPart part = GetSceneObjectPart(objectID);
2073 if (part == null) 2126 if (part == null)
2074 return; 2127 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 ad41e88..253adae 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -93,6 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
93 // TODO: need to figure out how allow client agents but deny 93 // TODO: need to figure out how allow client agents but deny
94 // root agents when ACL denies access to root agent 94 // root agents when ACL denies access to root agent
95 public bool m_strictAccessControl = true; 95 public bool m_strictAccessControl = true;
96 public bool m_seeIntoBannedRegion = false;
96 public int MaxUndoCount = 5; 97 public int MaxUndoCount = 5;
97 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 98 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
98 public bool LoginLock = false; 99 public bool LoginLock = false;
@@ -114,6 +115,7 @@ namespace OpenSim.Region.Framework.Scenes
114 protected ModuleLoader m_moduleLoader; 115 protected ModuleLoader m_moduleLoader;
115 protected AgentCircuitManager m_authenticateHandler; 116 protected AgentCircuitManager m_authenticateHandler;
116 protected SceneCommunicationService m_sceneGridService; 117 protected SceneCommunicationService m_sceneGridService;
118 protected ISnmpModule m_snmpService = null;
117 119
118 protected ISimulationDataService m_SimulationDataService; 120 protected ISimulationDataService m_SimulationDataService;
119 protected IEstateDataService m_EstateDataService; 121 protected IEstateDataService m_EstateDataService;
@@ -170,7 +172,7 @@ namespace OpenSim.Region.Framework.Scenes
170 private int m_update_events = 1; 172 private int m_update_events = 1;
171 private int m_update_backup = 200; 173 private int m_update_backup = 200;
172 private int m_update_terrain = 50; 174 private int m_update_terrain = 50;
173// private int m_update_land = 1; 175 private int m_update_land = 10;
174 private int m_update_coarse_locations = 50; 176 private int m_update_coarse_locations = 50;
175 177
176 private int frameMS; 178 private int frameMS;
@@ -184,6 +186,7 @@ namespace OpenSim.Region.Framework.Scenes
184 private int landMS; 186 private int landMS;
185 private int lastCompletedFrame; 187 private int lastCompletedFrame;
186 188
189 public bool CombineRegions = false;
187 private bool m_physics_enabled = true; 190 private bool m_physics_enabled = true;
188 private bool m_scripts_enabled = true; 191 private bool m_scripts_enabled = true;
189 private string m_defaultScriptEngine; 192 private string m_defaultScriptEngine;
@@ -192,6 +195,8 @@ namespace OpenSim.Region.Framework.Scenes
192 private volatile bool shuttingdown; 195 private volatile bool shuttingdown;
193 196
194 private int m_lastUpdate; 197 private int m_lastUpdate;
198 private int m_lastIncoming;
199 private int m_lastOutgoing;
195 private bool m_firstHeartbeat = true; 200 private bool m_firstHeartbeat = true;
196 201
197 private object m_deleting_scene_object = new object(); 202 private object m_deleting_scene_object = new object();
@@ -244,6 +249,19 @@ namespace OpenSim.Region.Framework.Scenes
244 get { return m_sceneGridService; } 249 get { return m_sceneGridService; }
245 } 250 }
246 251
252 public ISnmpModule SnmpService
253 {
254 get
255 {
256 if (m_snmpService == null)
257 {
258 m_snmpService = RequestModuleInterface<ISnmpModule>();
259 }
260
261 return m_snmpService;
262 }
263 }
264
247 public ISimulationDataService SimulationDataService 265 public ISimulationDataService SimulationDataService
248 { 266 {
249 get 267 get
@@ -572,7 +590,10 @@ namespace OpenSim.Region.Framework.Scenes
572 m_regInfo = regInfo; 590 m_regInfo = regInfo;
573 m_regionHandle = m_regInfo.RegionHandle; 591 m_regionHandle = m_regInfo.RegionHandle;
574 m_regionName = m_regInfo.RegionName; 592 m_regionName = m_regInfo.RegionName;
593 m_datastore = m_regInfo.DataStore;
575 m_lastUpdate = Util.EnvironmentTickCount(); 594 m_lastUpdate = Util.EnvironmentTickCount();
595 m_lastIncoming = 0;
596 m_lastOutgoing = 0;
576 597
577 m_physicalPrim = physicalPrim; 598 m_physicalPrim = physicalPrim;
578 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor; 599 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
@@ -586,6 +607,8 @@ namespace OpenSim.Region.Framework.Scenes
586 #region Region Settings 607 #region Region Settings
587 608
588 // Load region settings 609 // Load region settings
610 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID);
611
589 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID); 612 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
590 if (estateDataService != null) 613 if (estateDataService != null)
591 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 614 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -663,9 +686,10 @@ namespace OpenSim.Region.Framework.Scenes
663 //Animation states 686 //Animation states
664 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 687 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
665 // TODO: Change default to true once the feature is supported 688 // TODO: Change default to true once the feature is supported
666 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 689 m_usePreJump = startupConfig.GetBoolean("enableprejump", true);
667
668 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 690 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
691
692 m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF");
669 if (RegionInfo.NonphysPrimMax > 0) 693 if (RegionInfo.NonphysPrimMax > 0)
670 { 694 {
671 m_maxNonphys = RegionInfo.NonphysPrimMax; 695 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -697,6 +721,7 @@ namespace OpenSim.Region.Framework.Scenes
697 m_persistAfter *= 10000000; 721 m_persistAfter *= 10000000;
698 722
699 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 723 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
724 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
700 725
701 IConfig packetConfig = m_config.Configs["PacketPool"]; 726 IConfig packetConfig = m_config.Configs["PacketPool"];
702 if (packetConfig != null) 727 if (packetConfig != null)
@@ -706,6 +731,8 @@ namespace OpenSim.Region.Framework.Scenes
706 } 731 }
707 732
708 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 733 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
734 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
735 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
709 736
710 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 737 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
711 if (m_generateMaptiles) 738 if (m_generateMaptiles)
@@ -730,9 +757,9 @@ namespace OpenSim.Region.Framework.Scenes
730 } 757 }
731 } 758 }
732 } 759 }
733 catch 760 catch (Exception e)
734 { 761 {
735 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 762 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
736 } 763 }
737 764
738 #endregion Region Config 765 #endregion Region Config
@@ -1107,7 +1134,9 @@ namespace OpenSim.Region.Framework.Scenes
1107 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1134 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1108 if (HeartbeatThread != null) 1135 if (HeartbeatThread != null)
1109 { 1136 {
1137 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1110 HeartbeatThread.Abort(); 1138 HeartbeatThread.Abort();
1139 Watchdog.RemoveThread(HeartbeatThread.ManagedThreadId);
1111 HeartbeatThread = null; 1140 HeartbeatThread = null;
1112 } 1141 }
1113 m_lastUpdate = Util.EnvironmentTickCount(); 1142 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1231,9 +1260,6 @@ namespace OpenSim.Region.Framework.Scenes
1231 { 1260 {
1232 while (!shuttingdown) 1261 while (!shuttingdown)
1233 Update(); 1262 Update();
1234
1235 m_lastUpdate = Util.EnvironmentTickCount();
1236 m_firstHeartbeat = false;
1237 } 1263 }
1238 catch (ThreadAbortException) 1264 catch (ThreadAbortException)
1239 { 1265 {
@@ -1339,12 +1365,12 @@ namespace OpenSim.Region.Framework.Scenes
1339 terrainMS = Util.EnvironmentTickCountSubtract(terMS); 1365 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1340 } 1366 }
1341 1367
1342 //if (Frame % m_update_land == 0) 1368 // if (Frame % m_update_land == 0)
1343 //{ 1369 // {
1344 // int ldMS = Util.EnvironmentTickCount(); 1370 // int ldMS = Util.EnvironmentTickCount();
1345 // UpdateLand(); 1371 // UpdateLand();
1346 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1372 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1347 //} 1373 // }
1348 1374
1349 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); 1375 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
1350 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1376 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
@@ -1426,12 +1452,16 @@ namespace OpenSim.Region.Framework.Scenes
1426 maintc = Util.EnvironmentTickCountSubtract(maintc); 1452 maintc = Util.EnvironmentTickCountSubtract(maintc);
1427 maintc = (int)(m_timespan * 1000) - maintc; 1453 maintc = (int)(m_timespan * 1000) - maintc;
1428 1454
1455
1456 m_lastUpdate = Util.EnvironmentTickCount();
1457 m_firstHeartbeat = false;
1458
1429 if (maintc > 0) 1459 if (maintc > 0)
1430 Thread.Sleep(maintc); 1460 Thread.Sleep(maintc);
1431 1461
1432 // Tell the watchdog that this thread is still alive 1462 // Tell the watchdog that this thread is still alive
1433 Watchdog.UpdateThread(); 1463 Watchdog.UpdateThread();
1434 } 1464 }
1435 1465
1436 public void AddGroupTarget(SceneObjectGroup grp) 1466 public void AddGroupTarget(SceneObjectGroup grp)
1437 { 1467 {
@@ -1447,9 +1477,9 @@ namespace OpenSim.Region.Framework.Scenes
1447 1477
1448 private void CheckAtTargets() 1478 private void CheckAtTargets()
1449 { 1479 {
1450 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1480 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1451 lock (m_groupsWithTargets) 1481 lock (m_groupsWithTargets)
1452 objs = m_groupsWithTargets.Values; 1482 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1453 1483
1454 foreach (SceneObjectGroup entry in objs) 1484 foreach (SceneObjectGroup entry in objs)
1455 entry.checkAtTargets(); 1485 entry.checkAtTargets();
@@ -1773,14 +1803,24 @@ namespace OpenSim.Region.Framework.Scenes
1773 /// <returns></returns> 1803 /// <returns></returns>
1774 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1804 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1775 { 1805 {
1806
1807 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1808 Vector3 wpos = Vector3.Zero;
1809 // Check for water surface intersection from above
1810 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1811 {
1812 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1813 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1814 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1815 wpos.Z = wheight;
1816 }
1817
1776 Vector3 pos = Vector3.Zero; 1818 Vector3 pos = Vector3.Zero;
1777 if (RayEndIsIntersection == (byte)1) 1819 if (RayEndIsIntersection == (byte)1)
1778 { 1820 {
1779 pos = RayEnd; 1821 pos = RayEnd;
1780 return pos;
1781 } 1822 }
1782 1823 else if (RayTargetID != UUID.Zero)
1783 if (RayTargetID != UUID.Zero)
1784 { 1824 {
1785 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1825 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1786 1826
@@ -1802,7 +1842,7 @@ namespace OpenSim.Region.Framework.Scenes
1802 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1842 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1803 1843
1804 // Un-comment out the following line to Get Raytrace results printed to the console. 1844 // Un-comment out the following line to Get Raytrace results printed to the console.
1805 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1845 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1806 float ScaleOffset = 0.5f; 1846 float ScaleOffset = 0.5f;
1807 1847
1808 // If we hit something 1848 // If we hit something
@@ -1825,13 +1865,10 @@ namespace OpenSim.Region.Framework.Scenes
1825 //pos.Z -= 0.25F; 1865 //pos.Z -= 0.25F;
1826 1866
1827 } 1867 }
1828
1829 return pos;
1830 } 1868 }
1831 else 1869 else
1832 { 1870 {
1833 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1871 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1834
1835 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1872 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1836 1873
1837 // Un-comment the following line to print the raytrace results to the console. 1874 // Un-comment the following line to print the raytrace results to the console.
@@ -1840,13 +1877,12 @@ namespace OpenSim.Region.Framework.Scenes
1840 if (ei.HitTF) 1877 if (ei.HitTF)
1841 { 1878 {
1842 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1879 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1843 } else 1880 }
1881 else
1844 { 1882 {
1845 // fall back to our stupid functionality 1883 // fall back to our stupid functionality
1846 pos = RayEnd; 1884 pos = RayEnd;
1847 } 1885 }
1848
1849 return pos;
1850 } 1886 }
1851 } 1887 }
1852 else 1888 else
@@ -1857,8 +1893,12 @@ namespace OpenSim.Region.Framework.Scenes
1857 //increase height so its above the ground. 1893 //increase height so its above the ground.
1858 //should be getting the normal of the ground at the rez point and using that? 1894 //should be getting the normal of the ground at the rez point and using that?
1859 pos.Z += scale.Z / 2f; 1895 pos.Z += scale.Z / 2f;
1860 return pos; 1896// return pos;
1861 } 1897 }
1898
1899 // check against posible water intercept
1900 if (wpos.Z > pos.Z) pos = wpos;
1901 return pos;
1862 } 1902 }
1863 1903
1864 1904
@@ -1942,7 +1982,10 @@ namespace OpenSim.Region.Framework.Scenes
1942 public bool AddRestoredSceneObject( 1982 public bool AddRestoredSceneObject(
1943 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1983 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1944 { 1984 {
1945 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1985 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1986 if (result)
1987 sceneObject.IsDeleted = false;
1988 return result;
1946 } 1989 }
1947 1990
1948 /// <summary> 1991 /// <summary>
@@ -2032,6 +2075,15 @@ namespace OpenSim.Region.Framework.Scenes
2032 /// </summary> 2075 /// </summary>
2033 public void DeleteAllSceneObjects() 2076 public void DeleteAllSceneObjects()
2034 { 2077 {
2078 DeleteAllSceneObjects(false);
2079 }
2080
2081 /// <summary>
2082 /// Delete every object from the scene. This does not include attachments worn by avatars.
2083 /// </summary>
2084 public void DeleteAllSceneObjects(bool exceptNoCopy)
2085 {
2086 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2035 lock (Entities) 2087 lock (Entities)
2036 { 2088 {
2037 EntityBase[] entities = Entities.GetEntities(); 2089 EntityBase[] entities = Entities.GetEntities();
@@ -2040,11 +2092,24 @@ namespace OpenSim.Region.Framework.Scenes
2040 if (e is SceneObjectGroup) 2092 if (e is SceneObjectGroup)
2041 { 2093 {
2042 SceneObjectGroup sog = (SceneObjectGroup)e; 2094 SceneObjectGroup sog = (SceneObjectGroup)e;
2043 if (!sog.IsAttachment) 2095 if (sog != null && !sog.IsAttachment)
2044 DeleteSceneObject((SceneObjectGroup)e, false); 2096 {
2097 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2098 {
2099 DeleteSceneObject((SceneObjectGroup)e, false);
2100 }
2101 else
2102 {
2103 toReturn.Add((SceneObjectGroup)e);
2104 }
2105 }
2045 } 2106 }
2046 } 2107 }
2047 } 2108 }
2109 if (toReturn.Count > 0)
2110 {
2111 returnObjects(toReturn.ToArray(), UUID.Zero);
2112 }
2048 } 2113 }
2049 2114
2050 /// <summary> 2115 /// <summary>
@@ -2093,6 +2158,8 @@ namespace OpenSim.Region.Framework.Scenes
2093 } 2158 }
2094 2159
2095 group.DeleteGroupFromScene(silent); 2160 group.DeleteGroupFromScene(silent);
2161 if (!silent)
2162 SendKillObject(new List<uint>() { group.LocalId });
2096 2163
2097// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2164// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2098 } 2165 }
@@ -2445,10 +2512,17 @@ namespace OpenSim.Region.Framework.Scenes
2445 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2512 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2446 public bool AddSceneObject(SceneObjectGroup sceneObject) 2513 public bool AddSceneObject(SceneObjectGroup sceneObject)
2447 { 2514 {
2515 if (sceneObject.OwnerID == UUID.Zero)
2516 {
2517 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2518 return false;
2519 }
2520
2448 // If the user is banned, we won't let any of their objects 2521 // If the user is banned, we won't let any of their objects
2449 // enter. Period. 2522 // enter. Period.
2450 // 2523 //
2451 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2524 int flags = GetUserFlags(sceneObject.OwnerID);
2525 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2452 { 2526 {
2453 m_log.Info("[INTERREGION]: Denied prim crossing for " + 2527 m_log.Info("[INTERREGION]: Denied prim crossing for " +
2454 "banned avatar"); 2528 "banned avatar");
@@ -2492,15 +2566,28 @@ namespace OpenSim.Region.Framework.Scenes
2492 2566
2493 if (AttachmentsModule != null) 2567 if (AttachmentsModule != null)
2494 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2568 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2569
2570 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2495 } 2571 }
2496 else 2572 else
2497 { 2573 {
2574 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2498 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2575 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2499 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2576 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2500 } 2577 }
2578 if (sceneObject.OwnerID == UUID.Zero)
2579 {
2580 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2581 return false;
2582 }
2501 } 2583 }
2502 else 2584 else
2503 { 2585 {
2586 if (sceneObject.OwnerID == UUID.Zero)
2587 {
2588 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2589 return false;
2590 }
2504 AddRestoredSceneObject(sceneObject, true, false); 2591 AddRestoredSceneObject(sceneObject, true, false);
2505 2592
2506 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2593 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2530,6 +2617,24 @@ namespace OpenSim.Region.Framework.Scenes
2530 return 2; // StateSource.PrimCrossing 2617 return 2; // StateSource.PrimCrossing
2531 } 2618 }
2532 2619
2620 public int GetUserFlags(UUID user)
2621 {
2622 //Unfortunately the SP approach means that the value is cached until region is restarted
2623 /*
2624 ScenePresence sp;
2625 if (TryGetScenePresence(user, out sp))
2626 {
2627 return sp.UserFlags;
2628 }
2629 else
2630 {
2631 */
2632 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2633 if (uac == null)
2634 return 0;
2635 return uac.UserFlags;
2636 //}
2637 }
2533 #endregion 2638 #endregion
2534 2639
2535 #region Add/Remove Avatar Methods 2640 #region Add/Remove Avatar Methods
@@ -2550,6 +2655,7 @@ namespace OpenSim.Region.Framework.Scenes
2550 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2655 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2551 2656
2552 CheckHeartbeat(); 2657 CheckHeartbeat();
2658 ScenePresence presence;
2553 2659
2554 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here 2660 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here
2555 { 2661 {
@@ -2573,7 +2679,7 @@ namespace OpenSim.Region.Framework.Scenes
2573 } 2679 }
2574 } 2680 }
2575 2681
2576 if (GetScenePresence(client.AgentId) != null) 2682 if (TryGetScenePresence(client.AgentId, out presence))
2577 { 2683 {
2578 m_LastLogin = Util.EnvironmentTickCount(); 2684 m_LastLogin = Util.EnvironmentTickCount();
2579 2685
@@ -2582,7 +2688,14 @@ namespace OpenSim.Region.Framework.Scenes
2582 2688
2583 EventManager.TriggerOnNewClient(client); 2689 EventManager.TriggerOnNewClient(client);
2584 if (vialogin) 2690 if (vialogin)
2691 {
2585 EventManager.TriggerOnClientLogin(client); 2692 EventManager.TriggerOnClientLogin(client);
2693
2694 // Send initial parcel data
2695 Vector3 pos = presence.AbsolutePosition;
2696 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2697 land.SendLandUpdateToClient(presence.ControllingClient);
2698 }
2586 } 2699 }
2587 } 2700 }
2588 2701
@@ -2658,19 +2771,12 @@ namespace OpenSim.Region.Framework.Scenes
2658 // and the scene presence and the client, if they exist 2771 // and the scene presence and the client, if they exist
2659 try 2772 try
2660 { 2773 {
2661 // We need to wait for the client to make UDP contact first. 2774 ScenePresence sp = GetScenePresence(agentID);
2662 // It's the UDP contact that creates the scene presence 2775 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2663 ScenePresence sp = WaitGetScenePresence(agentID); 2776
2664 if (sp != null) 2777 if (sp != null)
2665 {
2666 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2667
2668 sp.ControllingClient.Close(); 2778 sp.ControllingClient.Close();
2669 } 2779
2670 else
2671 {
2672 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2673 }
2674 // BANG! SLASH! 2780 // BANG! SLASH!
2675 m_authenticateHandler.RemoveCircuit(agentID); 2781 m_authenticateHandler.RemoveCircuit(agentID);
2676 2782
@@ -2770,6 +2876,7 @@ namespace OpenSim.Region.Framework.Scenes
2770 client.OnFetchInventory += HandleFetchInventory; 2876 client.OnFetchInventory += HandleFetchInventory;
2771 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2877 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2772 client.OnCopyInventoryItem += CopyInventoryItem; 2878 client.OnCopyInventoryItem += CopyInventoryItem;
2879 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2773 client.OnMoveInventoryItem += MoveInventoryItem; 2880 client.OnMoveInventoryItem += MoveInventoryItem;
2774 client.OnRemoveInventoryItem += RemoveInventoryItem; 2881 client.OnRemoveInventoryItem += RemoveInventoryItem;
2775 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2882 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2947,15 +3054,16 @@ namespace OpenSim.Region.Framework.Scenes
2947 /// </summary> 3054 /// </summary>
2948 /// <param name="agentId">The avatar's Unique ID</param> 3055 /// <param name="agentId">The avatar's Unique ID</param>
2949 /// <param name="client">The IClientAPI for the client</param> 3056 /// <param name="client">The IClientAPI for the client</param>
2950 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3057 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2951 { 3058 {
2952 if (m_teleportModule != null) 3059 if (m_teleportModule != null)
2953 m_teleportModule.TeleportHome(agentId, client); 3060 return m_teleportModule.TeleportHome(agentId, client);
2954 else 3061 else
2955 { 3062 {
2956 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3063 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2957 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3064 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2958 } 3065 }
3066 return false;
2959 } 3067 }
2960 3068
2961 /// <summary> 3069 /// <summary>
@@ -3054,6 +3162,16 @@ namespace OpenSim.Region.Framework.Scenes
3054 /// <param name="flags"></param> 3162 /// <param name="flags"></param>
3055 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3163 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3056 { 3164 {
3165 //Add half the avatar's height so that the user doesn't fall through prims
3166 ScenePresence presence;
3167 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3168 {
3169 if (presence.Appearance != null)
3170 {
3171 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3172 }
3173 }
3174
3057 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3175 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3058 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3176 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3059 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3177 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3130,7 +3248,9 @@ namespace OpenSim.Region.Framework.Scenes
3130 regions.Remove(RegionInfo.RegionHandle); 3248 regions.Remove(RegionInfo.RegionHandle);
3131 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3249 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3132 } 3250 }
3251 m_log.Debug("[Scene] Beginning ClientClosed");
3133 m_eventManager.TriggerClientClosed(agentID, this); 3252 m_eventManager.TriggerClientClosed(agentID, this);
3253 m_log.Debug("[Scene] Finished ClientClosed");
3134 } 3254 }
3135 catch (NullReferenceException) 3255 catch (NullReferenceException)
3136 { 3256 {
@@ -3138,7 +3258,12 @@ namespace OpenSim.Region.Framework.Scenes
3138 // Avatar is already disposed :/ 3258 // Avatar is already disposed :/
3139 } 3259 }
3140 3260
3261 m_log.Debug("[Scene] Beginning OnRemovePresence");
3141 m_eventManager.TriggerOnRemovePresence(agentID); 3262 m_eventManager.TriggerOnRemovePresence(agentID);
3263 m_log.Debug("[Scene] Finished OnRemovePresence");
3264
3265 if (avatar != null && (!avatar.IsChildAgent))
3266 avatar.SaveChangedAttachments();
3142 3267
3143 if (avatar != null && (!avatar.IsChildAgent)) 3268 if (avatar != null && (!avatar.IsChildAgent))
3144 avatar.SaveChangedAttachments(); 3269 avatar.SaveChangedAttachments();
@@ -3147,7 +3272,7 @@ namespace OpenSim.Region.Framework.Scenes
3147 delegate(IClientAPI client) 3272 delegate(IClientAPI client)
3148 { 3273 {
3149 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3274 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3150 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3275 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3151 catch (NullReferenceException) { } 3276 catch (NullReferenceException) { }
3152 }); 3277 });
3153 3278
@@ -3158,8 +3283,11 @@ namespace OpenSim.Region.Framework.Scenes
3158 } 3283 }
3159 3284
3160 // Remove the avatar from the scene 3285 // Remove the avatar from the scene
3286 m_log.Debug("[Scene] Begin RemoveScenePresence");
3161 m_sceneGraph.RemoveScenePresence(agentID); 3287 m_sceneGraph.RemoveScenePresence(agentID);
3288 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3162 m_clientManager.Remove(agentID); 3289 m_clientManager.Remove(agentID);
3290 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3163 3291
3164 try 3292 try
3165 { 3293 {
@@ -3173,9 +3301,10 @@ namespace OpenSim.Region.Framework.Scenes
3173 { 3301 {
3174 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3302 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3175 } 3303 }
3176 3304 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3177 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3305 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3178 CleanDroppedAttachments(); 3306 CleanDroppedAttachments();
3307 m_log.Debug("[Scene] The avatar has left the building");
3179 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3308 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3180 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3309 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3181 } 3310 }
@@ -3206,18 +3335,24 @@ namespace OpenSim.Region.Framework.Scenes
3206 3335
3207 #region Entities 3336 #region Entities
3208 3337
3209 public void SendKillObject(uint localID) 3338 public void SendKillObject(List<uint> localIDs)
3210 { 3339 {
3211 SceneObjectPart part = GetSceneObjectPart(localID); 3340 List<uint> deleteIDs = new List<uint>();
3212 if (part != null) // It is a prim 3341
3342 foreach (uint localID in localIDs)
3213 { 3343 {
3214 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid 3344 SceneObjectPart part = GetSceneObjectPart(localID);
3345 if (part != null) // It is a prim
3215 { 3346 {
3216 if (part.ParentGroup.RootPart != part) // Child part 3347 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3217 return; 3348 {
3349 if (part.ParentGroup.RootPart != part) // Child part
3350 continue;
3351 }
3218 } 3352 }
3353 deleteIDs.Add(localID);
3219 } 3354 }
3220 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); 3355 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3221 } 3356 }
3222 3357
3223 #endregion 3358 #endregion
@@ -3235,7 +3370,6 @@ namespace OpenSim.Region.Framework.Scenes
3235 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3370 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3236 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3371 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3237 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3372 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3238 m_sceneGridService.KiPrimitive += SendKillObject;
3239 m_sceneGridService.OnGetLandData += GetLandData; 3373 m_sceneGridService.OnGetLandData += GetLandData;
3240 } 3374 }
3241 3375
@@ -3244,7 +3378,6 @@ namespace OpenSim.Region.Framework.Scenes
3244 /// </summary> 3378 /// </summary>
3245 public void UnRegisterRegionWithComms() 3379 public void UnRegisterRegionWithComms()
3246 { 3380 {
3247 m_sceneGridService.KiPrimitive -= SendKillObject;
3248 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3381 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3249 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3382 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3250 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3383 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3324,13 +3457,16 @@ namespace OpenSim.Region.Framework.Scenes
3324 sp = null; 3457 sp = null;
3325 } 3458 }
3326 3459
3327 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3328 3460
3329 //On login test land permisions 3461 //On login test land permisions
3330 if (vialogin) 3462 if (vialogin)
3331 { 3463 {
3332 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3464 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3465 if (cache != null)
3466 cache.Remove(agent.firstname + " " + agent.lastname);
3467 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3333 { 3468 {
3469 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3334 return false; 3470 return false;
3335 } 3471 }
3336 } 3472 }
@@ -3353,8 +3489,13 @@ namespace OpenSim.Region.Framework.Scenes
3353 3489
3354 try 3490 try
3355 { 3491 {
3356 if (!AuthorizeUser(agent, out reason)) 3492 // Always check estate if this is a login. Always
3357 return false; 3493 // check if banned regions are to be blacked out.
3494 if (vialogin || (!m_seeIntoBannedRegion))
3495 {
3496 if (!AuthorizeUser(agent.AgentID, out reason))
3497 return false;
3498 }
3358 } 3499 }
3359 catch (Exception e) 3500 catch (Exception e)
3360 { 3501 {
@@ -3456,6 +3597,8 @@ namespace OpenSim.Region.Framework.Scenes
3456 } 3597 }
3457 } 3598 }
3458 // Honor parcel landing type and position. 3599 // Honor parcel landing type and position.
3600 /*
3601 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3459 if (land != null) 3602 if (land != null)
3460 { 3603 {
3461 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3604 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3463,26 +3606,34 @@ namespace OpenSim.Region.Framework.Scenes
3463 agent.startpos = land.LandData.UserLocation; 3606 agent.startpos = land.LandData.UserLocation;
3464 } 3607 }
3465 } 3608 }
3609 */// This is now handled properly in ScenePresence.MakeRootAgent
3466 } 3610 }
3467 3611
3468 return true; 3612 return true;
3469 } 3613 }
3470 3614
3471 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3615 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3472 { 3616 {
3473 3617 reason = String.Empty;
3474 bool banned = land.IsBannedFromLand(agent.AgentID); 3618 if (Permissions.IsGod(agentID))
3475 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3619 return true;
3620
3621 ILandObject land = LandChannel.GetLandObject(posX, posY);
3622 if (land == null)
3623 return false;
3624
3625 bool banned = land.IsBannedFromLand(agentID);
3626 bool restricted = land.IsRestrictedFromLand(agentID);
3476 3627
3477 if (banned || restricted) 3628 if (banned || restricted)
3478 { 3629 {
3479 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3630 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3480 if (nearestParcel != null) 3631 if (nearestParcel != null)
3481 { 3632 {
3482 //Move agent to nearest allowed 3633 //Move agent to nearest allowed
3483 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3634 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3484 agent.startpos.X = newPosition.X; 3635 posX = newPosition.X;
3485 agent.startpos.Y = newPosition.Y; 3636 posY = newPosition.Y;
3486 } 3637 }
3487 else 3638 else
3488 { 3639 {
@@ -3538,19 +3689,19 @@ namespace OpenSim.Region.Framework.Scenes
3538 /// <param name="reason">outputs the reason to this string</param> 3689 /// <param name="reason">outputs the reason to this string</param>
3539 /// <returns>True if the region accepts this agent. False if it does not. False will 3690 /// <returns>True if the region accepts this agent. False if it does not. False will
3540 /// also return a reason.</returns> 3691 /// also return a reason.</returns>
3541 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 3692 protected virtual bool AuthorizeUser(UUID agentID, out string reason)
3542 { 3693 {
3543 reason = String.Empty; 3694 reason = String.Empty;
3544 3695
3545 if (!m_strictAccessControl) return true; 3696 if (!m_strictAccessControl) return true;
3546 if (Permissions.IsGod(agent.AgentID)) return true; 3697 if (Permissions.IsGod(agentID)) return true;
3547 3698
3548 if (AuthorizationService != null) 3699 if (AuthorizationService != null)
3549 { 3700 {
3550 if (!AuthorizationService.IsAuthorizedForRegion(agent.AgentID.ToString(), RegionInfo.RegionID.ToString(),out reason)) 3701 if (!AuthorizationService.IsAuthorizedForRegion(agentID.ToString(), RegionInfo.RegionID.ToString(),out reason))
3551 { 3702 {
3552 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3703 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the region",
3553 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3704 agentID, RegionInfo.RegionName);
3554 //reason = String.Format("You are not currently on the access list for {0}",RegionInfo.RegionName); 3705 //reason = String.Format("You are not currently on the access list for {0}",RegionInfo.RegionName);
3555 return false; 3706 return false;
3556 } 3707 }
@@ -3558,10 +3709,26 @@ namespace OpenSim.Region.Framework.Scenes
3558 3709
3559 if (m_regInfo.EstateSettings != null) 3710 if (m_regInfo.EstateSettings != null)
3560 { 3711 {
3561 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3712 int flags = GetUserFlags(agentID);
3713 if (m_regInfo.EstateSettings.IsBanned(agentID, flags))
3562 { 3714 {
3563 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3715 //Add some more info to help users
3564 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3716 if (!m_regInfo.EstateSettings.IsBanned(agentID, 32))
3717 {
3718 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the region requires age verification",
3719 agentID, RegionInfo.RegionName);
3720 reason = String.Format("Denied access to region {0}: Region requires age verification", RegionInfo.RegionName);
3721 return false;
3722 }
3723 if (!m_regInfo.EstateSettings.IsBanned(agentID, 4))
3724 {
3725 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} {1} because the region requires payment info on file",
3726 agentID, RegionInfo.RegionName);
3727 reason = String.Format("Denied access to region {0}: Region requires payment info on file", RegionInfo.RegionName);
3728 return false;
3729 }
3730 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {3} because the user is on the banlist",
3731 agentID, RegionInfo.RegionName);
3565 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 3732 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
3566 RegionInfo.RegionName); 3733 RegionInfo.RegionName);
3567 return false; 3734 return false;
@@ -3578,7 +3745,7 @@ namespace OpenSim.Region.Framework.Scenes
3578 if (groupsModule != null) 3745 if (groupsModule != null)
3579 { 3746 {
3580 GroupMembershipData[] GroupMembership = 3747 GroupMembershipData[] GroupMembership =
3581 groupsModule.GetMembershipData(agent.AgentID); 3748 groupsModule.GetMembershipData(agentID);
3582 3749
3583 if (GroupMembership != null) 3750 if (GroupMembership != null)
3584 { 3751 {
@@ -3607,44 +3774,16 @@ namespace OpenSim.Region.Framework.Scenes
3607 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 3774 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
3608 3775
3609 if (!m_regInfo.EstateSettings.PublicAccess && 3776 if (!m_regInfo.EstateSettings.PublicAccess &&
3610 !m_regInfo.EstateSettings.HasAccess(agent.AgentID) && 3777 !m_regInfo.EstateSettings.HasAccess(agentID) &&
3611 !groupAccess) 3778 !groupAccess)
3612 { 3779 {
3613 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 3780 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the estate",
3614 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3781 agentID, RegionInfo.RegionName);
3615 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 3782 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3616 RegionInfo.RegionName); 3783 RegionInfo.RegionName);
3617 return false; 3784 return false;
3618 } 3785 }
3619 3786
3620 // TODO: estate/region settings are not properly hooked up
3621 // to ILandObject.isRestrictedFromLand()
3622 // if (null != LandChannel)
3623 // {
3624 // // region seems to have local Id of 1
3625 // ILandObject land = LandChannel.GetLandObject(1);
3626 // if (null != land)
3627 // {
3628 // if (land.isBannedFromLand(agent.AgentID))
3629 // {
3630 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land",
3631 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3632 // reason = String.Format("Denied access to private region {0}: You are banned from that region.",
3633 // RegionInfo.RegionName);
3634 // return false;
3635 // }
3636
3637 // if (land.isRestrictedFromLand(agent.AgentID))
3638 // {
3639 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3640 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3641 // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3642 // RegionInfo.RegionName);
3643 // return false;
3644 // }
3645 // }
3646 // }
3647
3648 return true; 3787 return true;
3649 } 3788 }
3650 3789
@@ -3748,6 +3887,13 @@ namespace OpenSim.Region.Framework.Scenes
3748 3887
3749 // We have to wait until the viewer contacts this region after receiving EAC. 3888 // We have to wait until the viewer contacts this region after receiving EAC.
3750 // That calls AddNewClient, which finally creates the ScenePresence 3889 // That calls AddNewClient, which finally creates the ScenePresence
3890 int flags = GetUserFlags(cAgentData.AgentID);
3891 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3892 {
3893 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3894 return false;
3895 }
3896
3751 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3897 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3752 if (nearestParcel == null) 3898 if (nearestParcel == null)
3753 { 3899 {
@@ -3763,7 +3909,6 @@ namespace OpenSim.Region.Framework.Scenes
3763 return false; 3909 return false;
3764 } 3910 }
3765 3911
3766
3767 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3912 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3768 3913
3769 if (childAgentUpdate != null) 3914 if (childAgentUpdate != null)
@@ -3830,12 +3975,22 @@ namespace OpenSim.Region.Framework.Scenes
3830 return false; 3975 return false;
3831 } 3976 }
3832 3977
3978 public bool IncomingCloseAgent(UUID agentID)
3979 {
3980 return IncomingCloseAgent(agentID, false);
3981 }
3982
3983 public bool IncomingCloseChildAgent(UUID agentID)
3984 {
3985 return IncomingCloseAgent(agentID, true);
3986 }
3987
3833 /// <summary> 3988 /// <summary>
3834 /// Tell a single agent to disconnect from the region. 3989 /// Tell a single agent to disconnect from the region.
3835 /// </summary> 3990 /// </summary>
3836 /// <param name="regionHandle"></param>
3837 /// <param name="agentID"></param> 3991 /// <param name="agentID"></param>
3838 public bool IncomingCloseAgent(UUID agentID) 3992 /// <param name="childOnly"></param>
3993 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3839 { 3994 {
3840 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 3995 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3841 3996
@@ -3847,7 +4002,7 @@ namespace OpenSim.Region.Framework.Scenes
3847 { 4002 {
3848 m_sceneGraph.removeUserCount(false); 4003 m_sceneGraph.removeUserCount(false);
3849 } 4004 }
3850 else 4005 else if (!childOnly)
3851 { 4006 {
3852 m_sceneGraph.removeUserCount(true); 4007 m_sceneGraph.removeUserCount(true);
3853 } 4008 }
@@ -3863,9 +4018,12 @@ namespace OpenSim.Region.Framework.Scenes
3863 } 4018 }
3864 else 4019 else
3865 presence.ControllingClient.SendShutdownConnectionNotice(); 4020 presence.ControllingClient.SendShutdownConnectionNotice();
4021 presence.ControllingClient.Close(false);
4022 }
4023 else if (!childOnly)
4024 {
4025 presence.ControllingClient.Close(true);
3866 } 4026 }
3867
3868 presence.ControllingClient.Close();
3869 return true; 4027 return true;
3870 } 4028 }
3871 4029
@@ -4476,34 +4634,66 @@ namespace OpenSim.Region.Framework.Scenes
4476 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4634 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4477 } 4635 }
4478 4636
4479 public int GetHealth() 4637 public int GetHealth(out int flags, out string message)
4480 { 4638 {
4481 // Returns: 4639 // Returns:
4482 // 1 = sim is up and accepting http requests. The heartbeat has 4640 // 1 = sim is up and accepting http requests. The heartbeat has
4483 // stopped and the sim is probably locked up, but a remote 4641 // stopped and the sim is probably locked up, but a remote
4484 // admin restart may succeed 4642 // admin restart may succeed
4485 // 4643 //
4486 // 2 = Sim is up and the heartbeat is running. The sim is likely 4644 // 2 = Sim is up and the heartbeat is running. The sim is likely
4487 // usable for people within and logins _may_ work 4645 // usable for people within
4646 //
4647 // 3 = Sim is up and one packet thread is running. Sim is
4648 // unstable and will not accept new logins
4488 // 4649 //
4489 // 3 = We have seen a new user enter within the past 4 minutes 4650 // 4 = Sim is up and both packet threads are running. Sim is
4651 // likely usable
4652 //
4653 // 5 = We have seen a new user enter within the past 4 minutes
4490 // which can be seen as positive confirmation of sim health 4654 // which can be seen as positive confirmation of sim health
4491 // 4655 //
4656
4657 flags = 0;
4658 message = String.Empty;
4659
4660 CheckHeartbeat();
4661
4662 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4663 {
4664 // We're still starting
4665 // 0 means "in startup", it can't happen another way, since
4666 // to get here, we must be able to accept http connections
4667 return 0;
4668 }
4669
4492 int health=1; // Start at 1, means we're up 4670 int health=1; // Start at 1, means we're up
4493 4671
4494 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4672 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4673 {
4495 health+=1; 4674 health+=1;
4496 else 4675 flags |= 1;
4676 }
4677
4678 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4679 {
4680 health+=1;
4681 flags |= 2;
4682 }
4683
4684 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4685 {
4686 health+=1;
4687 flags |= 4;
4688 }
4689
4690 if (flags != 7)
4497 return health; 4691 return health;
4498 4692
4499 // A login in the last 4 mins? We can't be doing too badly 4693 // A login in the last 4 mins? We can't be doing too badly
4500 // 4694 //
4501 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4695 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4502 health++; 4696 health++;
4503 else
4504 return health;
4505
4506 CheckHeartbeat();
4507 4697
4508 return health; 4698 return health;
4509 } 4699 }
@@ -4696,7 +4886,7 @@ namespace OpenSim.Region.Framework.Scenes
4696 if (m_firstHeartbeat) 4886 if (m_firstHeartbeat)
4697 return; 4887 return;
4698 4888
4699 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4889 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 10000)
4700 StartTimer(); 4890 StartTimer();
4701 } 4891 }
4702 4892
@@ -5105,10 +5295,28 @@ namespace OpenSim.Region.Framework.Scenes
5105 }); 5295 });
5106 } 5296 }
5107 5297
5108 foreach (SceneObjectGroup grp in objectsToDelete) 5298 if (objectsToDelete.Count > 0)
5109 { 5299 {
5110 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID); 5300 m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count);
5111 DeleteSceneObject(grp, true); 5301 foreach (SceneObjectGroup grp in objectsToDelete)
5302 {
5303 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5304 DeleteSceneObject(grp, true);
5305 }
5306 m_log.Debug("[SCENE]: Finished dropped attachment deletion");
5307 }
5308 }
5309
5310 public void ThreadAlive(int threadCode)
5311 {
5312 switch(threadCode)
5313 {
5314 case 1: // Incoming
5315 m_lastIncoming = Util.EnvironmentTickCount();
5316 break;
5317 case 2: // Incoming
5318 m_lastOutgoing = Util.EnvironmentTickCount();
5319 break;
5112 } 5320 }
5113 } 5321 }
5114 5322
@@ -5120,6 +5328,14 @@ namespace OpenSim.Region.Framework.Scenes
5120 // child agent creation, thereby emulating the SL behavior. 5328 // child agent creation, thereby emulating the SL behavior.
5121 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5329 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5122 { 5330 {
5331 reason = "You are banned from the region";
5332
5333 if (Permissions.IsGod(agentID))
5334 {
5335 reason = String.Empty;
5336 return true;
5337 }
5338
5123 int num = m_sceneGraph.GetNumberOfScenePresences(); 5339 int num = m_sceneGraph.GetNumberOfScenePresences();
5124 5340
5125 if (num >= RegionInfo.RegionSettings.AgentLimit) 5341 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5131,6 +5347,36 @@ namespace OpenSim.Region.Framework.Scenes
5131 } 5347 }
5132 } 5348 }
5133 5349
5350 if (!AuthorizeUser(agentID, out reason))
5351 {
5352 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5353 return false;
5354 }
5355
5356 if (position == Vector3.Zero) // Teleport
5357 {
5358 float posX = 128.0f;
5359 float posY = 128.0f;
5360
5361 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5362 {
5363 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5364 return false;
5365 }
5366 }
5367 else // Walking
5368 {
5369 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5370 if (land == null)
5371 return false;
5372
5373 bool banned = land.IsBannedFromLand(agentID);
5374 bool restricted = land.IsRestrictedFromLand(agentID);
5375
5376 if (banned || restricted)
5377 return false;
5378 }
5379
5134 reason = String.Empty; 5380 reason = String.Empty;
5135 return true; 5381 return true;
5136 } 5382 }
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 a078291..39d4a29 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();
@@ -486,6 +527,30 @@ namespace OpenSim.Region.Framework.Scenes
486 m_updateList[obj.UUID] = obj; 527 m_updateList[obj.UUID] = obj;
487 } 528 }
488 529
530 public void FireAttachToBackup(SceneObjectGroup obj)
531 {
532 if (OnAttachToBackup != null)
533 {
534 OnAttachToBackup(obj);
535 }
536 }
537
538 public void FireDetachFromBackup(SceneObjectGroup obj)
539 {
540 if (OnDetachFromBackup != null)
541 {
542 OnDetachFromBackup(obj);
543 }
544 }
545
546 public void FireChangeBackup(SceneObjectGroup obj)
547 {
548 if (OnChangeBackup != null)
549 {
550 OnChangeBackup(obj);
551 }
552 }
553
489 /// <summary> 554 /// <summary>
490 /// Process all pending updates 555 /// Process all pending updates
491 /// </summary> 556 /// </summary>
@@ -621,7 +686,8 @@ namespace OpenSim.Region.Framework.Scenes
621 686
622 Entities[presence.UUID] = presence; 687 Entities[presence.UUID] = presence;
623 688
624 lock (m_presenceLock) 689 m_scenePresencesLock.EnterWriteLock();
690 try
625 { 691 {
626 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 692 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
627 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 693 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -645,6 +711,10 @@ namespace OpenSim.Region.Framework.Scenes
645 m_scenePresenceMap = newmap; 711 m_scenePresenceMap = newmap;
646 m_scenePresenceArray = newlist; 712 m_scenePresenceArray = newlist;
647 } 713 }
714 finally
715 {
716 m_scenePresencesLock.ExitWriteLock();
717 }
648 } 718 }
649 719
650 /// <summary> 720 /// <summary>
@@ -659,7 +729,8 @@ namespace OpenSim.Region.Framework.Scenes
659 agentID); 729 agentID);
660 } 730 }
661 731
662 lock (m_presenceLock) 732 m_scenePresencesLock.EnterWriteLock();
733 try
663 { 734 {
664 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 735 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
665 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 736 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -681,6 +752,10 @@ namespace OpenSim.Region.Framework.Scenes
681 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 752 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
682 } 753 }
683 } 754 }
755 finally
756 {
757 m_scenePresencesLock.ExitWriteLock();
758 }
684 } 759 }
685 760
686 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 761 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1363,8 +1438,13 @@ namespace OpenSim.Region.Framework.Scenes
1363 { 1438 {
1364 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1439 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1365 { 1440 {
1366 if (m_parentScene.AttachmentsModule != null) 1441 // Set the new attachment point data in the object
1367 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1442 byte attachmentPoint = group.GetAttachmentPoint();
1443 group.UpdateGroupPosition(pos);
1444 group.RootPart.IsAttachment = false;
1445 group.AbsolutePosition = group.RootPart.AttachedPos;
1446 group.SetAttachmentPoint(attachmentPoint);
1447 group.HasGroupChanged = true;
1368 } 1448 }
1369 else 1449 else
1370 { 1450 {
@@ -1617,10 +1697,13 @@ namespace OpenSim.Region.Framework.Scenes
1617 /// <param name="childPrims"></param> 1697 /// <param name="childPrims"></param>
1618 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1698 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1619 { 1699 {
1700 SceneObjectGroup parentGroup = root.ParentGroup;
1701 if (parentGroup == null) return;
1620 Monitor.Enter(m_updateLock); 1702 Monitor.Enter(m_updateLock);
1703
1621 try 1704 try
1622 { 1705 {
1623 SceneObjectGroup parentGroup = root.ParentGroup; 1706 parentGroup.areUpdatesSuspended = true;
1624 1707
1625 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1708 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1626 if (parentGroup != null) 1709 if (parentGroup != null)
@@ -1632,11 +1715,6 @@ namespace OpenSim.Region.Framework.Scenes
1632 1715
1633 if (child != null) 1716 if (child != null)
1634 { 1717 {
1635 // Make sure no child prim is set for sale
1636 // So that, on delink, no prims are unwittingly
1637 // left for sale and sold off
1638 child.RootPart.ObjectSaleType = 0;
1639 child.RootPart.SalePrice = 10;
1640 childGroups.Add(child); 1718 childGroups.Add(child);
1641 } 1719 }
1642 } 1720 }
@@ -1659,12 +1737,13 @@ namespace OpenSim.Region.Framework.Scenes
1659 // occur on link to invoke this elsewhere (such as object selection) 1737 // occur on link to invoke this elsewhere (such as object selection)
1660 parentGroup.RootPart.CreateSelected = true; 1738 parentGroup.RootPart.CreateSelected = true;
1661 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1739 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1662 parentGroup.HasGroupChanged = true;
1663 parentGroup.ScheduleGroupForFullUpdate();
1664
1665 } 1740 }
1666 finally 1741 finally
1667 { 1742 {
1743 parentGroup.areUpdatesSuspended = false;
1744 parentGroup.HasGroupChanged = true;
1745 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1746 parentGroup.ScheduleGroupForFullUpdate();
1668 Monitor.Exit(m_updateLock); 1747 Monitor.Exit(m_updateLock);
1669 } 1748 }
1670 } 1749 }
@@ -1696,21 +1775,24 @@ namespace OpenSim.Region.Framework.Scenes
1696 1775
1697 SceneObjectGroup group = part.ParentGroup; 1776 SceneObjectGroup group = part.ParentGroup;
1698 if (!affectedGroups.Contains(group)) 1777 if (!affectedGroups.Contains(group))
1778 {
1779 group.areUpdatesSuspended = true;
1699 affectedGroups.Add(group); 1780 affectedGroups.Add(group);
1781 }
1700 } 1782 }
1701 } 1783 }
1702 } 1784 }
1703 1785
1704 foreach (SceneObjectPart child in childParts) 1786 if (childParts.Count > 0)
1705 { 1787 {
1706 // Unlink all child parts from their groups 1788 foreach (SceneObjectPart child in childParts)
1707 // 1789 {
1708 child.ParentGroup.DelinkFromGroup(child, true); 1790 // Unlink all child parts from their groups
1709 1791 //
1710 // These are not in affected groups and will not be 1792 child.ParentGroup.DelinkFromGroup(child, true);
1711 // handled further. Do the honors here. 1793 child.ParentGroup.HasGroupChanged = true;
1712 child.ParentGroup.HasGroupChanged = true; 1794 child.ParentGroup.ScheduleGroupForFullUpdate();
1713 child.ParentGroup.ScheduleGroupForFullUpdate(); 1795 }
1714 } 1796 }
1715 1797
1716 foreach (SceneObjectPart root in rootParts) 1798 foreach (SceneObjectPart root in rootParts)
@@ -1720,56 +1802,68 @@ namespace OpenSim.Region.Framework.Scenes
1720 // However, editing linked parts and unlinking may be different 1802 // However, editing linked parts and unlinking may be different
1721 // 1803 //
1722 SceneObjectGroup group = root.ParentGroup; 1804 SceneObjectGroup group = root.ParentGroup;
1805 group.areUpdatesSuspended = true;
1723 1806
1724 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1807 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1725 int numChildren = newSet.Count; 1808 int numChildren = newSet.Count;
1726 1809
1810 if (numChildren == 1)
1811 break;
1812
1727 // If there are prims left in a link set, but the root is 1813 // If there are prims left in a link set, but the root is
1728 // slated for unlink, we need to do this 1814 // slated for unlink, we need to do this
1815 // Unlink the remaining set
1729 // 1816 //
1730 if (numChildren != 1) 1817 bool sendEventsToRemainder = true;
1731 { 1818 if (numChildren > 1)
1732 // Unlink the remaining set 1819 sendEventsToRemainder = false;
1733 //
1734 bool sendEventsToRemainder = true;
1735 if (numChildren > 1)
1736 sendEventsToRemainder = false;
1737 1820
1738 foreach (SceneObjectPart p in newSet) 1821 foreach (SceneObjectPart p in newSet)
1822 {
1823 if (p != group.RootPart)
1739 { 1824 {
1740 if (p != group.RootPart) 1825 group.DelinkFromGroup(p, sendEventsToRemainder);
1741 group.DelinkFromGroup(p, sendEventsToRemainder); 1826 if (numChildren > 2)
1827 {
1828 p.ParentGroup.areUpdatesSuspended = true;
1829 }
1830 else
1831 {
1832 p.ParentGroup.HasGroupChanged = true;
1833 p.ParentGroup.ScheduleGroupForFullUpdate();
1834 }
1742 } 1835 }
1836 }
1743 1837
1744 // If there is more than one prim remaining, we 1838 // If there is more than one prim remaining, we
1745 // need to re-link 1839 // need to re-link
1840 //
1841 if (numChildren > 2)
1842 {
1843 // Remove old root
1844 //
1845 if (newSet.Contains(root))
1846 newSet.Remove(root);
1847
1848 // Preserve link ordering
1746 // 1849 //
1747 if (numChildren > 2) 1850 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1748 { 1851 {
1749 // Remove old root 1852 return a.LinkNum.CompareTo(b.LinkNum);
1750 // 1853 });
1751 if (newSet.Contains(root))
1752 newSet.Remove(root);
1753
1754 // Preserve link ordering
1755 //
1756 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1757 {
1758 return a.LinkNum.CompareTo(b.LinkNum);
1759 });
1760 1854
1761 // Determine new root 1855 // Determine new root
1762 // 1856 //
1763 SceneObjectPart newRoot = newSet[0]; 1857 SceneObjectPart newRoot = newSet[0];
1764 newSet.RemoveAt(0); 1858 newSet.RemoveAt(0);
1765 1859
1766 foreach (SceneObjectPart newChild in newSet) 1860 foreach (SceneObjectPart newChild in newSet)
1767 newChild.UpdateFlag = 0; 1861 newChild.UpdateFlag = 0;
1768 1862
1769 LinkObjects(newRoot, newSet); 1863 newRoot.ParentGroup.areUpdatesSuspended = true;
1770 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1864 LinkObjects(newRoot, newSet);
1771 affectedGroups.Add(newRoot.ParentGroup); 1865 if (!affectedGroups.Contains(newRoot.ParentGroup))
1772 } 1866 affectedGroups.Add(newRoot.ParentGroup);
1773 } 1867 }
1774 } 1868 }
1775 1869
@@ -1777,8 +1871,14 @@ namespace OpenSim.Region.Framework.Scenes
1777 // 1871 //
1778 foreach (SceneObjectGroup g in affectedGroups) 1872 foreach (SceneObjectGroup g in affectedGroups)
1779 { 1873 {
1874 // Child prims that have been unlinked and deleted will
1875 // return unless the root is deleted. This will remove them
1876 // from the database. They will be rewritten immediately,
1877 // minus the rows for the unlinked child prims.
1878 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1780 g.TriggerScriptChangedEvent(Changed.LINK); 1879 g.TriggerScriptChangedEvent(Changed.LINK);
1781 g.HasGroupChanged = true; // Persist 1880 g.HasGroupChanged = true; // Persist
1881 g.areUpdatesSuspended = false;
1782 g.ScheduleGroupForFullUpdate(); 1882 g.ScheduleGroupForFullUpdate();
1783 } 1883 }
1784 } 1884 }
@@ -1896,9 +1996,6 @@ namespace OpenSim.Region.Framework.Scenes
1896 child.ApplyNextOwnerPermissions(); 1996 child.ApplyNextOwnerPermissions();
1897 } 1997 }
1898 } 1998 }
1899
1900 copy.RootPart.ObjectSaleType = 0;
1901 copy.RootPart.SalePrice = 10;
1902 } 1999 }
1903 2000
1904 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2001 // 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 42ac9aa..482597d 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
@@ -131,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 183 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
132 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 184 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 185 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 186 public bool HasGroupChangedDueToDelink { get; set; }
135 187
136 private bool isTimeToPersist() 188 private bool isTimeToPersist()
137 { 189 {
@@ -141,8 +193,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 193 return false;
142 if (m_scene.ShuttingDown) 194 if (m_scene.ShuttingDown)
143 return true; 195 return true;
196
197 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
198 {
199 m_maxPersistTime = m_scene.m_persistAfter;
200 m_minPersistTime = m_scene.m_dontPersistBefore;
201 }
202
144 long currentTime = DateTime.Now.Ticks; 203 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 204
205 if (timeLastChanged == 0) timeLastChanged = currentTime;
206 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
207
208 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 209 return true;
147 return false; 210 return false;
148 } 211 }
@@ -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 //{
@@ -481,6 +575,7 @@ namespace OpenSim.Region.Framework.Scenes
481 /// </summary> 575 /// </summary>
482 public SceneObjectGroup() 576 public SceneObjectGroup()
483 { 577 {
578
484 } 579 }
485 580
486 /// <summary> 581 /// <summary>
@@ -497,7 +592,7 @@ namespace OpenSim.Region.Framework.Scenes
497 /// Constructor. This object is added to the scene later via AttachToScene() 592 /// Constructor. This object is added to the scene later via AttachToScene()
498 /// </summary> 593 /// </summary>
499 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 594 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
500 { 595 {
501 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 596 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
502 } 597 }
503 598
@@ -545,6 +640,9 @@ namespace OpenSim.Region.Framework.Scenes
545 /// </summary> 640 /// </summary>
546 public virtual void AttachToBackup() 641 public virtual void AttachToBackup()
547 { 642 {
643 if (IsAttachment) return;
644 m_scene.SceneGraph.FireAttachToBackup(this);
645
548 if (InSceneBackup) 646 if (InSceneBackup)
549 { 647 {
550 //m_log.DebugFormat( 648 //m_log.DebugFormat(
@@ -587,6 +685,9 @@ namespace OpenSim.Region.Framework.Scenes
587 685
588 ApplyPhysics(m_scene.m_physicalPrim); 686 ApplyPhysics(m_scene.m_physicalPrim);
589 687
688 if (RootPart.PhysActor != null)
689 RootPart.Buoyancy = RootPart.Buoyancy;
690
590 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 691 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
591 // for the same object with very different properties. The caller must schedule the update. 692 // for the same object with very different properties. The caller must schedule the update.
592 //ScheduleGroupForFullUpdate(); 693 //ScheduleGroupForFullUpdate();
@@ -660,9 +761,9 @@ namespace OpenSim.Region.Framework.Scenes
660 result.normal = inter.normal; 761 result.normal = inter.normal;
661 result.distance = inter.distance; 762 result.distance = inter.distance;
662 } 763 }
764
663 } 765 }
664 } 766 }
665
666 return result; 767 return result;
667 } 768 }
668 769
@@ -682,17 +783,19 @@ namespace OpenSim.Region.Framework.Scenes
682 minZ = 8192f; 783 minZ = 8192f;
683 784
684 SceneObjectPart[] parts = m_parts.GetArray(); 785 SceneObjectPart[] parts = m_parts.GetArray();
685 for (int i = 0; i < parts.Length; i++) 786 foreach (SceneObjectPart part in parts)
686 { 787 {
687 SceneObjectPart part = parts[i];
688
689 Vector3 worldPos = part.GetWorldPosition(); 788 Vector3 worldPos = part.GetWorldPosition();
690 Vector3 offset = worldPos - AbsolutePosition; 789 Vector3 offset = worldPos - AbsolutePosition;
691 Quaternion worldRot; 790 Quaternion worldRot;
692 if (part.ParentID == 0) 791 if (part.ParentID == 0)
792 {
693 worldRot = part.RotationOffset; 793 worldRot = part.RotationOffset;
794 }
694 else 795 else
796 {
695 worldRot = part.GetWorldRotation(); 797 worldRot = part.GetWorldRotation();
798 }
696 799
697 Vector3 frontTopLeft; 800 Vector3 frontTopLeft;
698 Vector3 frontTopRight; 801 Vector3 frontTopRight;
@@ -704,6 +807,8 @@ namespace OpenSim.Region.Framework.Scenes
704 Vector3 backBottomLeft; 807 Vector3 backBottomLeft;
705 Vector3 backBottomRight; 808 Vector3 backBottomRight;
706 809
810 // Vector3[] corners = new Vector3[8];
811
707 Vector3 orig = Vector3.Zero; 812 Vector3 orig = Vector3.Zero;
708 813
709 frontTopLeft.X = orig.X - (part.Scale.X / 2); 814 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -738,6 +843,38 @@ namespace OpenSim.Region.Framework.Scenes
738 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 843 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
739 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 844 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
740 845
846
847
848 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
849 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
850 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
851 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
852 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
853 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
854 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
855 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
856
857 //for (int i = 0; i < 8; i++)
858 //{
859 // corners[i] = corners[i] * worldRot;
860 // corners[i] += offset;
861
862 // if (corners[i].X > maxX)
863 // maxX = corners[i].X;
864 // if (corners[i].X < minX)
865 // minX = corners[i].X;
866
867 // if (corners[i].Y > maxY)
868 // maxY = corners[i].Y;
869 // if (corners[i].Y < minY)
870 // minY = corners[i].Y;
871
872 // if (corners[i].Z > maxZ)
873 // maxZ = corners[i].Y;
874 // if (corners[i].Z < minZ)
875 // minZ = corners[i].Z;
876 //}
877
741 frontTopLeft = frontTopLeft * worldRot; 878 frontTopLeft = frontTopLeft * worldRot;
742 frontTopRight = frontTopRight * worldRot; 879 frontTopRight = frontTopRight * worldRot;
743 frontBottomLeft = frontBottomLeft * worldRot; 880 frontBottomLeft = frontBottomLeft * worldRot;
@@ -759,6 +896,15 @@ namespace OpenSim.Region.Framework.Scenes
759 backTopLeft += offset; 896 backTopLeft += offset;
760 backTopRight += offset; 897 backTopRight += offset;
761 898
899 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
900 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
901 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
902 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
903 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
904 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
905 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
906 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
907
762 if (frontTopRight.X > maxX) 908 if (frontTopRight.X > maxX)
763 maxX = frontTopRight.X; 909 maxX = frontTopRight.X;
764 if (frontTopLeft.X > maxX) 910 if (frontTopLeft.X > maxX)
@@ -904,15 +1050,20 @@ namespace OpenSim.Region.Framework.Scenes
904 1050
905 public void SaveScriptedState(XmlTextWriter writer) 1051 public void SaveScriptedState(XmlTextWriter writer)
906 { 1052 {
1053 SaveScriptedState(writer, false);
1054 }
1055
1056 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1057 {
907 XmlDocument doc = new XmlDocument(); 1058 XmlDocument doc = new XmlDocument();
908 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1059 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
909 1060
910 SceneObjectPart[] parts = m_parts.GetArray(); 1061 SceneObjectPart[] parts = m_parts.GetArray();
911 for (int i = 0; i < parts.Length; i++) 1062 for (int i = 0; i < parts.Length; i++)
912 { 1063 {
913 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1064 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
914 foreach (KeyValuePair<UUID, string> kvp in pstates) 1065 foreach (KeyValuePair<UUID, string> kvp in pstates)
915 states.Add(kvp.Key, kvp.Value); 1066 states[kvp.Key] = kvp.Value;
916 } 1067 }
917 1068
918 if (states.Count > 0) 1069 if (states.Count > 0)
@@ -931,6 +1082,118 @@ namespace OpenSim.Region.Framework.Scenes
931 } 1082 }
932 } 1083 }
933 1084
1085 /// <summary>
1086 /// Add the avatar to this linkset (avatar is sat).
1087 /// </summary>
1088 /// <param name="agentID"></param>
1089 public void AddAvatar(UUID agentID)
1090 {
1091 ScenePresence presence;
1092 if (m_scene.TryGetScenePresence(agentID, out presence))
1093 {
1094 if (!m_linkedAvatars.Contains(presence))
1095 {
1096 m_linkedAvatars.Add(presence);
1097 }
1098 }
1099 }
1100
1101 /// <summary>
1102 /// Delete the avatar from this linkset (avatar is unsat).
1103 /// </summary>
1104 /// <param name="agentID"></param>
1105 public void DeleteAvatar(UUID agentID)
1106 {
1107 ScenePresence presence;
1108 if (m_scene.TryGetScenePresence(agentID, out presence))
1109 {
1110 if (m_linkedAvatars.Contains(presence))
1111 {
1112 m_linkedAvatars.Remove(presence);
1113 }
1114 }
1115 }
1116
1117 /// <summary>
1118 /// Returns the list of linked presences (avatars sat on this group)
1119 /// </summary>
1120 /// <param name="agentID"></param>
1121 public List<ScenePresence> GetLinkedAvatars()
1122 {
1123 return m_linkedAvatars;
1124 }
1125
1126 /// <summary>
1127 /// Attach this scene object to the given avatar.
1128 /// </summary>
1129 /// <param name="agentID"></param>
1130 /// <param name="attachmentpoint"></param>
1131 /// <param name="AttachOffset"></param>
1132 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent)
1133 {
1134 ScenePresence avatar = m_scene.GetScenePresence(agentID);
1135 if (avatar != null)
1136 {
1137 // don't attach attachments to child agents
1138 if (avatar.IsChildAgent) return;
1139
1140// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
1141
1142 DetachFromBackup();
1143
1144 // Remove from database and parcel prim count
1145 m_scene.DeleteFromStorage(UUID);
1146 m_scene.EventManager.TriggerParcelPrimCountTainted();
1147
1148 m_rootPart.AttachedAvatar = agentID;
1149
1150 //Anakin Lohner bug #3839
1151 lock (m_parts)
1152 {
1153 foreach (SceneObjectPart p in m_parts.GetArray())
1154 {
1155 p.AttachedAvatar = agentID;
1156 }
1157 }
1158
1159 if (m_rootPart.PhysActor != null)
1160 {
1161 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor);
1162 m_rootPart.PhysActor = null;
1163 }
1164
1165 AbsolutePosition = AttachOffset;
1166 m_rootPart.AttachedPos = AttachOffset;
1167 m_rootPart.IsAttachment = true;
1168
1169 m_rootPart.SetParentLocalId(avatar.LocalId);
1170 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
1171
1172 avatar.AddAttachment(this);
1173
1174 if (!silent)
1175 {
1176 // Killing it here will cause the client to deselect it
1177 // It then reappears on the avatar, deselected
1178 // through the full update below
1179 //
1180 if (IsSelected)
1181 {
1182 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1183 }
1184
1185 IsSelected = false; // fudge....
1186 ScheduleGroupForFullUpdate();
1187 }
1188 }
1189 else
1190 {
1191 m_log.WarnFormat(
1192 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1193 UUID, agentID, Scene.RegionInfo.RegionName);
1194 }
1195 }
1196
934 public byte GetAttachmentPoint() 1197 public byte GetAttachmentPoint()
935 { 1198 {
936 return m_rootPart.Shape.State; 1199 return m_rootPart.Shape.State;
@@ -1057,7 +1320,10 @@ namespace OpenSim.Region.Framework.Scenes
1057 public void AddPart(SceneObjectPart part) 1320 public void AddPart(SceneObjectPart part)
1058 { 1321 {
1059 part.SetParent(this); 1322 part.SetParent(this);
1060 part.LinkNum = m_parts.Add(part.UUID, part); 1323 m_parts.Add(part.UUID, part);
1324
1325 part.LinkNum = m_parts.Count;
1326
1061 if (part.LinkNum == 2 && RootPart != null) 1327 if (part.LinkNum == 2 && RootPart != null)
1062 RootPart.LinkNum = 1; 1328 RootPart.LinkNum = 1;
1063 } 1329 }
@@ -1141,7 +1407,7 @@ namespace OpenSim.Region.Framework.Scenes
1141 1407
1142 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1408 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1143 { 1409 {
1144 part.StoreUndoState(); 1410 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1145 part.OnGrab(offsetPos, remoteClient); 1411 part.OnGrab(offsetPos, remoteClient);
1146 } 1412 }
1147 1413
@@ -1161,6 +1427,11 @@ namespace OpenSim.Region.Framework.Scenes
1161 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1427 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1162 public void DeleteGroupFromScene(bool silent) 1428 public void DeleteGroupFromScene(bool silent)
1163 { 1429 {
1430 // We need to keep track of this state in case this group is still queued for backup.
1431 m_isDeleted = true;
1432
1433 DetachFromBackup();
1434
1164 SceneObjectPart[] parts = m_parts.GetArray(); 1435 SceneObjectPart[] parts = m_parts.GetArray();
1165 for (int i = 0; i < parts.Length; i++) 1436 for (int i = 0; i < parts.Length; i++)
1166 { 1437 {
@@ -1172,13 +1443,11 @@ namespace OpenSim.Region.Framework.Scenes
1172 avatar.StandUp(); 1443 avatar.StandUp();
1173 1444
1174 if (!silent) 1445 if (!silent)
1175 {
1176 part.UpdateFlag = 0; 1446 part.UpdateFlag = 0;
1177 if (part == m_rootPart)
1178 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1179 }
1180 }); 1447 });
1181 } 1448 }
1449
1450
1182 } 1451 }
1183 1452
1184 public void AddScriptLPS(int count) 1453 public void AddScriptLPS(int count)
@@ -1275,7 +1544,12 @@ namespace OpenSim.Region.Framework.Scenes
1275 1544
1276 public void SetOwnerId(UUID userId) 1545 public void SetOwnerId(UUID userId)
1277 { 1546 {
1278 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1547 ForEachPart(delegate(SceneObjectPart part)
1548 {
1549
1550 part.OwnerID = userId;
1551
1552 });
1279 } 1553 }
1280 1554
1281 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1555 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1307,11 +1581,17 @@ namespace OpenSim.Region.Framework.Scenes
1307 return; 1581 return;
1308 } 1582 }
1309 1583
1584 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1585 return;
1586
1310 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1587 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1311 // any exception propogate upwards. 1588 // any exception propogate upwards.
1312 try 1589 try
1313 { 1590 {
1314 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1591 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1592 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1593 m_scene.LoadingPrims) // Land may not be valid yet
1594
1315 { 1595 {
1316 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1596 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1317 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1597 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1338,6 +1618,7 @@ namespace OpenSim.Region.Framework.Scenes
1338 } 1618 }
1339 } 1619 }
1340 } 1620 }
1621
1341 } 1622 }
1342 1623
1343 if (m_scene.UseBackup && HasGroupChanged) 1624 if (m_scene.UseBackup && HasGroupChanged)
@@ -1345,6 +1626,20 @@ namespace OpenSim.Region.Framework.Scenes
1345 // don't backup while it's selected or you're asking for changes mid stream. 1626 // don't backup while it's selected or you're asking for changes mid stream.
1346 if (isTimeToPersist() || forcedBackup) 1627 if (isTimeToPersist() || forcedBackup)
1347 { 1628 {
1629 if (m_rootPart.PhysActor != null &&
1630 (!m_rootPart.PhysActor.IsPhysical))
1631 {
1632 // Possible ghost prim
1633 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1634 {
1635 foreach (SceneObjectPart part in m_parts.GetArray())
1636 {
1637 // Re-set physics actor positions and
1638 // orientations
1639 part.GroupPosition = m_rootPart.GroupPosition;
1640 }
1641 }
1642 }
1348// m_log.DebugFormat( 1643// m_log.DebugFormat(
1349// "[SCENE]: Storing {0}, {1} in {2}", 1644// "[SCENE]: Storing {0}, {1} in {2}",
1350// Name, UUID, m_scene.RegionInfo.RegionName); 1645// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1408,86 +1703,90 @@ namespace OpenSim.Region.Framework.Scenes
1408 /// <returns></returns> 1703 /// <returns></returns>
1409 public SceneObjectGroup Copy(bool userExposed) 1704 public SceneObjectGroup Copy(bool userExposed)
1410 { 1705 {
1411 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1706 SceneObjectGroup dupe;
1412 dupe.m_isBackedUp = false; 1707 try
1413 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1708 {
1414 1709 m_dupeInProgress = true;
1415 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1710 dupe = (SceneObjectGroup)MemberwiseClone();
1416 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1711 dupe.m_isBackedUp = false;
1417 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1712 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1418 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1419 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1420 // then restore it's attachment state
1421
1422 // This is only necessary when userExposed is false!
1423 1713
1424 bool previousAttachmentStatus = dupe.RootPart.IsAttachment; 1714 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1425 1715 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1426 if (!userExposed) 1716 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1427 dupe.RootPart.IsAttachment = true; 1717 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1718 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1719 // then restore it's attachment state
1428 1720
1429 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1721 // This is only necessary when userExposed is false!
1430 1722
1431 if (!userExposed) 1723 bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
1432 {
1433 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1434 }
1435 1724
1436 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1725 if (!userExposed)
1437 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1726 dupe.RootPart.IsAttachment = true;
1438 1727
1439 if (userExposed) 1728 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1440 dupe.m_rootPart.TrimPermissions();
1441 1729
1442 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1730 if (!userExposed)
1443
1444 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1445 { 1731 {
1446 return p1.LinkNum.CompareTo(p2.LinkNum); 1732 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1447 } 1733 }
1448 );
1449 1734
1450 foreach (SceneObjectPart part in partList) 1735 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1451 { 1736 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1452 SceneObjectPart newPart; 1737
1453 if (part.UUID != m_rootPart.UUID) 1738 if (userExposed)
1739 dupe.m_rootPart.TrimPermissions();
1740
1741 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1742
1743 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1744 {
1745 return p1.LinkNum.CompareTo(p2.LinkNum);
1746 }
1747 );
1748
1749 foreach (SceneObjectPart part in partList)
1454 { 1750 {
1455 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1751 if (part.UUID != m_rootPart.UUID)
1456 newPart.LinkNum = part.LinkNum; 1752 {
1753 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1754
1755 newPart.LinkNum = part.LinkNum;
1756 }
1757
1758 // Need to duplicate the physics actor as well
1759 if (part.PhysActor != null && userExposed)
1760 {
1761 PrimitiveBaseShape pbs = part.Shape;
1762
1763 part.PhysActor
1764 = m_scene.PhysicsScene.AddPrimShape(
1765 string.Format("{0}/{1}", part.Name, part.UUID),
1766 pbs,
1767 part.AbsolutePosition,
1768 part.Scale,
1769 part.RotationOffset,
1770 part.PhysActor.IsPhysical);
1771 part.PhysActor.SetMaterial((int)part.Material);
1772
1773 part.PhysActor.LocalID = part.LocalId;
1774 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1775 }
1457 } 1776 }
1458 else 1777 if (userExposed)
1459 { 1778 {
1460 newPart = dupe.m_rootPart; 1779 dupe.UpdateParentIDs();
1461 } 1780 dupe.HasGroupChanged = true;
1781 dupe.AttachToBackup();
1462 1782
1463 // Need to duplicate the physics actor as well 1783 ScheduleGroupForFullUpdate();
1464 if (part.PhysActor != null && userExposed)
1465 {
1466 PrimitiveBaseShape pbs = part.Shape;
1467
1468 newPart.PhysActor
1469 = m_scene.PhysicsScene.AddPrimShape(
1470 part.LocalId,
1471 string.Format("{0}/{1}", part.Name, part.UUID),
1472 pbs,
1473 part.AbsolutePosition,
1474 part.Scale,
1475 part.RotationOffset,
1476 part.PhysActor.IsPhysical);
1477
1478 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1479 } 1784 }
1480 } 1785 }
1481 1786 finally
1482 if (userExposed)
1483 { 1787 {
1484 dupe.UpdateParentIDs(); 1788 m_dupeInProgress = false;
1485 dupe.HasGroupChanged = true;
1486 dupe.AttachToBackup();
1487
1488 ScheduleGroupForFullUpdate();
1489 } 1789 }
1490
1491 return dupe; 1790 return dupe;
1492 } 1791 }
1493 1792
@@ -1632,6 +1931,7 @@ namespace OpenSim.Region.Framework.Scenes
1632 return Vector3.Zero; 1931 return Vector3.Zero;
1633 } 1932 }
1634 1933
1934 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1635 public void moveToTarget(Vector3 target, float tau) 1935 public void moveToTarget(Vector3 target, float tau)
1636 { 1936 {
1637 SceneObjectPart rootpart = m_rootPart; 1937 SceneObjectPart rootpart = m_rootPart;
@@ -1671,20 +1971,55 @@ namespace OpenSim.Region.Framework.Scenes
1671 SceneObjectPart rootpart = m_rootPart; 1971 SceneObjectPart rootpart = m_rootPart;
1672 if (rootpart != null) 1972 if (rootpart != null)
1673 { 1973 {
1674 if (rootpart.PhysActor != null) 1974 if (IsAttachment)
1675 { 1975 {
1676 rootpart.PhysActor.PIDActive = false; 1976 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1977 if (avatar != null) avatar.StopMoveToPosition();
1978 }
1979 else
1980 {
1981 if (rootpart.PhysActor != null)
1982 {
1983 rootpart.PhysActor.PIDActive = false;
1984 }
1677 } 1985 }
1678 } 1986 }
1679 } 1987 }
1680 1988
1989 public void rotLookAt(Quaternion target, float strength, float damping)
1990 {
1991 SceneObjectPart rootpart = m_rootPart;
1992 if (rootpart != null)
1993 {
1994 if (IsAttachment)
1995 {
1996 /*
1997 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
1998 if (avatar != null)
1999 {
2000 Rotate the Av?
2001 } */
2002 }
2003 else
2004 {
2005 if (rootpart.PhysActor != null)
2006 { // APID must be implemented in your physics system for this to function.
2007 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2008 rootpart.PhysActor.APIDStrength = strength;
2009 rootpart.PhysActor.APIDDamping = damping;
2010 rootpart.PhysActor.APIDActive = true;
2011 }
2012 }
2013 }
2014 }
2015
1681 public void stopLookAt() 2016 public void stopLookAt()
1682 { 2017 {
1683 SceneObjectPart rootpart = m_rootPart; 2018 SceneObjectPart rootpart = m_rootPart;
1684 if (rootpart != null) 2019 if (rootpart != null)
1685 { 2020 {
1686 if (rootpart.PhysActor != null) 2021 if (rootpart.PhysActor != null)
1687 { 2022 { // APID must be implemented in your physics system for this to function.
1688 rootpart.PhysActor.APIDActive = false; 2023 rootpart.PhysActor.APIDActive = false;
1689 } 2024 }
1690 } 2025 }
@@ -1750,6 +2085,8 @@ namespace OpenSim.Region.Framework.Scenes
1750 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2085 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1751 { 2086 {
1752 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2087 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2088 newPart.SetParent(this);
2089
1753 AddPart(newPart); 2090 AddPart(newPart);
1754 2091
1755 SetPartAsNonRoot(newPart); 2092 SetPartAsNonRoot(newPart);
@@ -1898,11 +2235,11 @@ namespace OpenSim.Region.Framework.Scenes
1898 /// Immediately send a full update for this scene object. 2235 /// Immediately send a full update for this scene object.
1899 /// </summary> 2236 /// </summary>
1900 public void SendGroupFullUpdate() 2237 public void SendGroupFullUpdate()
1901 { 2238 {
1902 if (IsDeleted) 2239 if (IsDeleted)
1903 return; 2240 return;
1904 2241
1905// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2242// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1906 2243
1907 RootPart.SendFullUpdateToAllClients(); 2244 RootPart.SendFullUpdateToAllClients();
1908 2245
@@ -2091,12 +2428,15 @@ namespace OpenSim.Region.Framework.Scenes
2091 part.LinkNum += objectGroup.PrimCount; 2428 part.LinkNum += objectGroup.PrimCount;
2092 } 2429 }
2093 } 2430 }
2431 }
2094 2432
2095 linkPart.LinkNum = 2; 2433 linkPart.LinkNum = 2;
2096 2434
2097 linkPart.SetParent(this); 2435 linkPart.SetParent(this);
2098 linkPart.CreateSelected = true; 2436 linkPart.CreateSelected = true;
2099 2437
2438 lock (m_parts.SyncRoot)
2439 {
2100 //if (linkPart.PhysActor != null) 2440 //if (linkPart.PhysActor != null)
2101 //{ 2441 //{
2102 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2442 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2254,6 +2594,8 @@ namespace OpenSim.Region.Framework.Scenes
2254 /// <param name="objectGroup"></param> 2594 /// <param name="objectGroup"></param>
2255 public virtual void DetachFromBackup() 2595 public virtual void DetachFromBackup()
2256 { 2596 {
2597 m_scene.SceneGraph.FireDetachFromBackup(this);
2598
2257 if (m_isBackedUp) 2599 if (m_isBackedUp)
2258 m_scene.EventManager.OnBackup -= ProcessBackup; 2600 m_scene.EventManager.OnBackup -= ProcessBackup;
2259 2601
@@ -2272,7 +2614,8 @@ namespace OpenSim.Region.Framework.Scenes
2272 2614
2273 axPos *= parentRot; 2615 axPos *= parentRot;
2274 part.OffsetPosition = axPos; 2616 part.OffsetPosition = axPos;
2275 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2617 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2618 part.GroupPosition = newPos;
2276 part.OffsetPosition = Vector3.Zero; 2619 part.OffsetPosition = Vector3.Zero;
2277 part.RotationOffset = worldRot; 2620 part.RotationOffset = worldRot;
2278 2621
@@ -2283,7 +2626,7 @@ namespace OpenSim.Region.Framework.Scenes
2283 2626
2284 part.LinkNum = linkNum; 2627 part.LinkNum = linkNum;
2285 2628
2286 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2629 part.OffsetPosition = newPos - AbsolutePosition;
2287 2630
2288 Quaternion rootRotation = m_rootPart.RotationOffset; 2631 Quaternion rootRotation = m_rootPart.RotationOffset;
2289 2632
@@ -2293,7 +2636,7 @@ namespace OpenSim.Region.Framework.Scenes
2293 2636
2294 parentRot = m_rootPart.RotationOffset; 2637 parentRot = m_rootPart.RotationOffset;
2295 oldRot = part.RotationOffset; 2638 oldRot = part.RotationOffset;
2296 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2639 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2297 part.RotationOffset = newRot; 2640 part.RotationOffset = newRot;
2298 } 2641 }
2299 2642
@@ -2544,8 +2887,12 @@ namespace OpenSim.Region.Framework.Scenes
2544 } 2887 }
2545 } 2888 }
2546 2889
2890 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2547 for (int i = 0; i < parts.Length; i++) 2891 for (int i = 0; i < parts.Length; i++)
2548 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2892 {
2893 if (parts[i] != RootPart)
2894 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2895 }
2549 } 2896 }
2550 } 2897 }
2551 2898
@@ -2558,6 +2905,17 @@ namespace OpenSim.Region.Framework.Scenes
2558 } 2905 }
2559 } 2906 }
2560 2907
2908
2909
2910 /// <summary>
2911 /// Gets the number of parts
2912 /// </summary>
2913 /// <returns></returns>
2914 public int GetPartCount()
2915 {
2916 return Parts.Count();
2917 }
2918
2561 /// <summary> 2919 /// <summary>
2562 /// Update the texture entry for this part 2920 /// Update the texture entry for this part
2563 /// </summary> 2921 /// </summary>
@@ -2619,11 +2977,9 @@ namespace OpenSim.Region.Framework.Scenes
2619 scale.Y = m_scene.m_maxNonphys; 2977 scale.Y = m_scene.m_maxNonphys;
2620 if (scale.Z > m_scene.m_maxNonphys) 2978 if (scale.Z > m_scene.m_maxNonphys)
2621 scale.Z = m_scene.m_maxNonphys; 2979 scale.Z = m_scene.m_maxNonphys;
2622
2623 SceneObjectPart part = GetChildPart(localID); 2980 SceneObjectPart part = GetChildPart(localID);
2624 if (part != null) 2981 if (part != null)
2625 { 2982 {
2626 part.Resize(scale);
2627 if (part.PhysActor != null) 2983 if (part.PhysActor != null)
2628 { 2984 {
2629 if (part.PhysActor.IsPhysical) 2985 if (part.PhysActor.IsPhysical)
@@ -2638,7 +2994,7 @@ namespace OpenSim.Region.Framework.Scenes
2638 part.PhysActor.Size = scale; 2994 part.PhysActor.Size = scale;
2639 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor); 2995 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2640 } 2996 }
2641 //if (part.UUID != m_rootPart.UUID) 2997 part.Resize(scale);
2642 2998
2643 HasGroupChanged = true; 2999 HasGroupChanged = true;
2644 part.TriggerScriptChangedEvent(Changed.SCALE); 3000 part.TriggerScriptChangedEvent(Changed.SCALE);
@@ -2661,7 +3017,6 @@ namespace OpenSim.Region.Framework.Scenes
2661 SceneObjectPart part = GetChildPart(localID); 3017 SceneObjectPart part = GetChildPart(localID);
2662 if (part != null) 3018 if (part != null)
2663 { 3019 {
2664 part.IgnoreUndoUpdate = true;
2665 if (scale.X > m_scene.m_maxNonphys) 3020 if (scale.X > m_scene.m_maxNonphys)
2666 scale.X = m_scene.m_maxNonphys; 3021 scale.X = m_scene.m_maxNonphys;
2667 if (scale.Y > m_scene.m_maxNonphys) 3022 if (scale.Y > m_scene.m_maxNonphys)
@@ -2698,7 +3053,7 @@ namespace OpenSim.Region.Framework.Scenes
2698 3053
2699 if (part.PhysActor != null && part.PhysActor.IsPhysical) 3054 if (part.PhysActor != null && part.PhysActor.IsPhysical)
2700 { 3055 {
2701 if (oldSize.X * x > m_scene.m_maxPhys) 3056 if (oldSize.X*x > m_scene.m_maxPhys)
2702 { 3057 {
2703 f = m_scene.m_maxPhys / oldSize.X; 3058 f = m_scene.m_maxPhys / oldSize.X;
2704 a = f / x; 3059 a = f / x;
@@ -2706,7 +3061,7 @@ namespace OpenSim.Region.Framework.Scenes
2706 y *= a; 3061 y *= a;
2707 z *= a; 3062 z *= a;
2708 } 3063 }
2709 if (oldSize.Y * y > m_scene.m_maxPhys) 3064 if (oldSize.Y*y > m_scene.m_maxPhys)
2710 { 3065 {
2711 f = m_scene.m_maxPhys / oldSize.Y; 3066 f = m_scene.m_maxPhys / oldSize.Y;
2712 a = f / y; 3067 a = f / y;
@@ -2714,7 +3069,7 @@ namespace OpenSim.Region.Framework.Scenes
2714 y *= a; 3069 y *= a;
2715 z *= a; 3070 z *= a;
2716 } 3071 }
2717 if (oldSize.Z * z > m_scene.m_maxPhys) 3072 if (oldSize.Z*z > m_scene.m_maxPhys)
2718 { 3073 {
2719 f = m_scene.m_maxPhys / oldSize.Z; 3074 f = m_scene.m_maxPhys / oldSize.Z;
2720 a = f / z; 3075 a = f / z;
@@ -2725,7 +3080,7 @@ namespace OpenSim.Region.Framework.Scenes
2725 } 3080 }
2726 else 3081 else
2727 { 3082 {
2728 if (oldSize.X * x > m_scene.m_maxNonphys) 3083 if (oldSize.X*x > m_scene.m_maxNonphys)
2729 { 3084 {
2730 f = m_scene.m_maxNonphys / oldSize.X; 3085 f = m_scene.m_maxNonphys / oldSize.X;
2731 a = f / x; 3086 a = f / x;
@@ -2733,7 +3088,7 @@ namespace OpenSim.Region.Framework.Scenes
2733 y *= a; 3088 y *= a;
2734 z *= a; 3089 z *= a;
2735 } 3090 }
2736 if (oldSize.Y * y > m_scene.m_maxNonphys) 3091 if (oldSize.Y*y > m_scene.m_maxNonphys)
2737 { 3092 {
2738 f = m_scene.m_maxNonphys / oldSize.Y; 3093 f = m_scene.m_maxNonphys / oldSize.Y;
2739 a = f / y; 3094 a = f / y;
@@ -2741,7 +3096,7 @@ namespace OpenSim.Region.Framework.Scenes
2741 y *= a; 3096 y *= a;
2742 z *= a; 3097 z *= a;
2743 } 3098 }
2744 if (oldSize.Z * z > m_scene.m_maxNonphys) 3099 if (oldSize.Z*z > m_scene.m_maxNonphys)
2745 { 3100 {
2746 f = m_scene.m_maxNonphys / oldSize.Z; 3101 f = m_scene.m_maxNonphys / oldSize.Z;
2747 a = f / z; 3102 a = f / z;
@@ -2751,7 +3106,6 @@ namespace OpenSim.Region.Framework.Scenes
2751 } 3106 }
2752 } 3107 }
2753 obPart.IgnoreUndoUpdate = false; 3108 obPart.IgnoreUndoUpdate = false;
2754 obPart.StoreUndoState();
2755 } 3109 }
2756 } 3110 }
2757 } 3111 }
@@ -2759,8 +3113,13 @@ namespace OpenSim.Region.Framework.Scenes
2759 Vector3 prevScale = part.Scale; 3113 Vector3 prevScale = part.Scale;
2760 prevScale.X *= x; 3114 prevScale.X *= x;
2761 prevScale.Y *= y; 3115 prevScale.Y *= y;
2762 prevScale.Z *= z; 3116 prevScale.Z *= z;;
3117
3118 part.IgnoreUndoUpdate = false;
3119 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3120 part.IgnoreUndoUpdate = true;
2763 part.Resize(prevScale); 3121 part.Resize(prevScale);
3122 part.IgnoreUndoUpdate = false;
2764 3123
2765 parts = m_parts.GetArray(); 3124 parts = m_parts.GetArray();
2766 for (int i = 0; i < parts.Length; i++) 3125 for (int i = 0; i < parts.Length; i++)
@@ -2769,19 +3128,26 @@ namespace OpenSim.Region.Framework.Scenes
2769 obPart.IgnoreUndoUpdate = true; 3128 obPart.IgnoreUndoUpdate = true;
2770 if (obPart.UUID != m_rootPart.UUID) 3129 if (obPart.UUID != m_rootPart.UUID)
2771 { 3130 {
2772 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3131 if (obPart.UUID != m_rootPart.UUID)
2773 currentpos.X *= x; 3132 {
2774 currentpos.Y *= y; 3133 obPart.IgnoreUndoUpdate = false;
2775 currentpos.Z *= z; 3134 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
2776 Vector3 newSize = new Vector3(obPart.Scale); 3135 obPart.IgnoreUndoUpdate = true;
2777 newSize.X *= x; 3136
2778 newSize.Y *= y; 3137 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2779 newSize.Z *= z; 3138 currentpos.X *= x;
2780 obPart.Resize(newSize); 3139 currentpos.Y *= y;
2781 obPart.UpdateOffSet(currentpos); 3140 currentpos.Z *= z;
3141 Vector3 newSize = new Vector3(obPart.Scale);
3142 newSize.X *= x;
3143 newSize.Y *= y;
3144 newSize.Z *= z;
3145 obPart.Resize(newSize);
3146 obPart.UpdateOffSet(currentpos);
3147 }
3148 obPart.IgnoreUndoUpdate = false;
2782 } 3149 }
2783 obPart.IgnoreUndoUpdate = false; 3150 obPart.IgnoreUndoUpdate = false;
2784 obPart.StoreUndoState();
2785 } 3151 }
2786 3152
2787 if (part.PhysActor != null) 3153 if (part.PhysActor != null)
@@ -2791,7 +3157,6 @@ namespace OpenSim.Region.Framework.Scenes
2791 } 3157 }
2792 3158
2793 part.IgnoreUndoUpdate = false; 3159 part.IgnoreUndoUpdate = false;
2794 part.StoreUndoState();
2795 HasGroupChanged = true; 3160 HasGroupChanged = true;
2796 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE); 3161 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
2797 ScheduleGroupForTerseUpdate(); 3162 ScheduleGroupForTerseUpdate();
@@ -2808,14 +3173,11 @@ namespace OpenSim.Region.Framework.Scenes
2808 /// <param name="pos"></param> 3173 /// <param name="pos"></param>
2809 public void UpdateGroupPosition(Vector3 pos) 3174 public void UpdateGroupPosition(Vector3 pos)
2810 { 3175 {
2811 SceneObjectPart[] parts = m_parts.GetArray();
2812 for (int i = 0; i < parts.Length; i++)
2813 parts[i].StoreUndoState();
2814
2815 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3176 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2816 { 3177 {
2817 if (IsAttachment) 3178 if (IsAttachment)
2818 { 3179 {
3180 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2819 m_rootPart.AttachedPos = pos; 3181 m_rootPart.AttachedPos = pos;
2820 } 3182 }
2821 if (RootPart.GetStatusSandbox()) 3183 if (RootPart.GetStatusSandbox())
@@ -2849,7 +3211,7 @@ namespace OpenSim.Region.Framework.Scenes
2849 3211
2850 SceneObjectPart[] parts = m_parts.GetArray(); 3212 SceneObjectPart[] parts = m_parts.GetArray();
2851 for (int i = 0; i < parts.Length; i++) 3213 for (int i = 0; i < parts.Length; i++)
2852 parts[i].StoreUndoState(); 3214 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2853 3215
2854 if (part != null) 3216 if (part != null)
2855 { 3217 {
@@ -2874,7 +3236,7 @@ namespace OpenSim.Region.Framework.Scenes
2874 { 3236 {
2875 SceneObjectPart[] parts = m_parts.GetArray(); 3237 SceneObjectPart[] parts = m_parts.GetArray();
2876 for (int i = 0; i < parts.Length; i++) 3238 for (int i = 0; i < parts.Length; i++)
2877 parts[i].StoreUndoState(); 3239 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
2878 3240
2879 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3241 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2880 Vector3 oldPos = 3242 Vector3 oldPos =
@@ -2895,10 +3257,27 @@ namespace OpenSim.Region.Framework.Scenes
2895 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3257 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2896 } 3258 }
2897 3259
2898 AbsolutePosition = newPos; 3260 //We have to set undoing here because otherwise an undo state will be saved
3261 if (!m_rootPart.Undoing)
3262 {
3263 m_rootPart.Undoing = true;
3264 AbsolutePosition = newPos;
3265 m_rootPart.Undoing = false;
3266 }
3267 else
3268 {
3269 AbsolutePosition = newPos;
3270 }
2899 3271
2900 HasGroupChanged = true; 3272 HasGroupChanged = true;
2901 ScheduleGroupForTerseUpdate(); 3273 if (m_rootPart.Undoing)
3274 {
3275 ScheduleGroupForFullUpdate();
3276 }
3277 else
3278 {
3279 ScheduleGroupForTerseUpdate();
3280 }
2902 } 3281 }
2903 3282
2904 public void OffsetForNewRegion(Vector3 offset) 3283 public void OffsetForNewRegion(Vector3 offset)
@@ -2918,7 +3297,7 @@ namespace OpenSim.Region.Framework.Scenes
2918 { 3297 {
2919 SceneObjectPart[] parts = m_parts.GetArray(); 3298 SceneObjectPart[] parts = m_parts.GetArray();
2920 for (int i = 0; i < parts.Length; i++) 3299 for (int i = 0; i < parts.Length; i++)
2921 parts[i].StoreUndoState(); 3300 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2922 3301
2923 m_rootPart.UpdateRotation(rot); 3302 m_rootPart.UpdateRotation(rot);
2924 3303
@@ -2942,7 +3321,7 @@ namespace OpenSim.Region.Framework.Scenes
2942 { 3321 {
2943 SceneObjectPart[] parts = m_parts.GetArray(); 3322 SceneObjectPart[] parts = m_parts.GetArray();
2944 for (int i = 0; i < parts.Length; i++) 3323 for (int i = 0; i < parts.Length; i++)
2945 parts[i].StoreUndoState(); 3324 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
2946 3325
2947 m_rootPart.UpdateRotation(rot); 3326 m_rootPart.UpdateRotation(rot);
2948 3327
@@ -2967,10 +3346,9 @@ namespace OpenSim.Region.Framework.Scenes
2967 public void UpdateSingleRotation(Quaternion rot, uint localID) 3346 public void UpdateSingleRotation(Quaternion rot, uint localID)
2968 { 3347 {
2969 SceneObjectPart part = GetChildPart(localID); 3348 SceneObjectPart part = GetChildPart(localID);
2970
2971 SceneObjectPart[] parts = m_parts.GetArray(); 3349 SceneObjectPart[] parts = m_parts.GetArray();
2972 for (int i = 0; i < parts.Length; i++) 3350 for (int i = 0; i < parts.Length; i++)
2973 parts[i].StoreUndoState(); 3351 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2974 3352
2975 if (part != null) 3353 if (part != null)
2976 { 3354 {
@@ -2998,15 +3376,24 @@ namespace OpenSim.Region.Framework.Scenes
2998 if (part.UUID == m_rootPart.UUID) 3376 if (part.UUID == m_rootPart.UUID)
2999 { 3377 {
3000 UpdateRootRotation(rot); 3378 UpdateRootRotation(rot);
3001 AbsolutePosition = pos; 3379 if (!m_rootPart.Undoing)
3380 {
3381 m_rootPart.Undoing = true;
3382 AbsolutePosition = pos;
3383 m_rootPart.Undoing = false;
3384 }
3385 else
3386 {
3387 AbsolutePosition = pos;
3388 }
3002 } 3389 }
3003 else 3390 else
3004 { 3391 {
3392 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3005 part.IgnoreUndoUpdate = true; 3393 part.IgnoreUndoUpdate = true;
3006 part.UpdateRotation(rot); 3394 part.UpdateRotation(rot);
3007 part.OffsetPosition = pos; 3395 part.OffsetPosition = pos;
3008 part.IgnoreUndoUpdate = false; 3396 part.IgnoreUndoUpdate = false;
3009 part.StoreUndoState();
3010 } 3397 }
3011 } 3398 }
3012 } 3399 }
@@ -3020,8 +3407,16 @@ namespace OpenSim.Region.Framework.Scenes
3020 Quaternion axRot = rot; 3407 Quaternion axRot = rot;
3021 Quaternion oldParentRot = m_rootPart.RotationOffset; 3408 Quaternion oldParentRot = m_rootPart.RotationOffset;
3022 3409
3023 m_rootPart.StoreUndoState(); 3410 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3024 m_rootPart.UpdateRotation(rot); 3411 bool cancelUndo = false;
3412 if (!m_rootPart.Undoing)
3413 {
3414 m_rootPart.Undoing = true;
3415 cancelUndo = true;
3416 }
3417
3418 //Don't use UpdateRotation because it schedules an update prematurely
3419 m_rootPart.RotationOffset = rot;
3025 if (m_rootPart.PhysActor != null) 3420 if (m_rootPart.PhysActor != null)
3026 { 3421 {
3027 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3422 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -3036,28 +3431,22 @@ namespace OpenSim.Region.Framework.Scenes
3036 { 3431 {
3037 prim.IgnoreUndoUpdate = true; 3432 prim.IgnoreUndoUpdate = true;
3038 Vector3 axPos = prim.OffsetPosition; 3433 Vector3 axPos = prim.OffsetPosition;
3434
3039 axPos *= oldParentRot; 3435 axPos *= oldParentRot;
3040 axPos *= Quaternion.Inverse(axRot); 3436 axPos *= Quaternion.Inverse(axRot);
3041 prim.OffsetPosition = axPos; 3437 prim.OffsetPosition = axPos;
3042 Quaternion primsRot = prim.RotationOffset; 3438
3043 Quaternion newRot = primsRot * oldParentRot; 3439 prim.RotationOffset *= Quaternion.Inverse(prim.GetWorldRotation()) * (oldParentRot * prim.RotationOffset);
3044 newRot *= Quaternion.Inverse(axRot); 3440
3045 prim.RotationOffset = newRot; 3441 prim.IgnoreUndoUpdate = false;
3046 prim.ScheduleTerseUpdate();
3047 } 3442 }
3048 } 3443 }
3049 3444 if (cancelUndo == true)
3050 for (int i = 0; i < parts.Length; i++)
3051 { 3445 {
3052 SceneObjectPart childpart = parts[i]; 3446 m_rootPart.Undoing = false;
3053 if (childpart != m_rootPart)
3054 {
3055 childpart.IgnoreUndoUpdate = false;
3056 childpart.StoreUndoState();
3057 }
3058 } 3447 }
3059 3448 HasGroupChanged = true;
3060 m_rootPart.ScheduleTerseUpdate(); 3449 ScheduleGroupForFullUpdate();
3061 } 3450 }
3062 3451
3063 #endregion 3452 #endregion
@@ -3280,7 +3669,6 @@ namespace OpenSim.Region.Framework.Scenes
3280 public float GetMass() 3669 public float GetMass()
3281 { 3670 {
3282 float retmass = 0f; 3671 float retmass = 0f;
3283
3284 SceneObjectPart[] parts = m_parts.GetArray(); 3672 SceneObjectPart[] parts = m_parts.GetArray();
3285 for (int i = 0; i < parts.Length; i++) 3673 for (int i = 0; i < parts.Length; i++)
3286 retmass += parts[i].GetMass(); 3674 retmass += parts[i].GetMass();
@@ -3396,6 +3784,14 @@ namespace OpenSim.Region.Framework.Scenes
3396 SetFromItemID(uuid); 3784 SetFromItemID(uuid);
3397 } 3785 }
3398 3786
3787 public void ResetOwnerChangeFlag()
3788 {
3789 ForEachPart(delegate(SceneObjectPart part)
3790 {
3791 part.ResetOwnerChangeFlag();
3792 });
3793 }
3794
3399 #endregion 3795 #endregion
3400 } 3796 }
3401} 3797}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index f3879f0..ff1d520 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.
@@ -189,7 +190,15 @@ namespace OpenSim.Region.Framework.Scenes
189 190
190 public UUID FromFolderID; 191 public UUID FromFolderID;
191 192
192 193 // The following two are to hold the attachment data
194 // while an object is inworld
195 [XmlIgnore]
196 public byte AttachPoint = 0;
197
198 [XmlIgnore]
199 public Vector3 AttachOffset = Vector3.Zero;
200
201 [XmlIgnore]
193 public int STATUS_ROTATE_X; 202 public int STATUS_ROTATE_X;
194 203
195 204
@@ -284,6 +293,7 @@ namespace OpenSim.Region.Framework.Scenes
284 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 293 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
285 private Vector3 m_sitTargetPosition; 294 private Vector3 m_sitTargetPosition;
286 private string m_sitAnimation = "SIT"; 295 private string m_sitAnimation = "SIT";
296 private bool m_occupied; // KF if any av is sitting on this prim
287 private string m_text = String.Empty; 297 private string m_text = String.Empty;
288 private string m_touchName = String.Empty; 298 private string m_touchName = String.Empty;
289 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5); 299 private readonly UndoStack<UndoState> m_undo = new UndoStack<UndoState>(5);
@@ -328,6 +338,7 @@ namespace OpenSim.Region.Framework.Scenes
328 protected Vector3 m_lastAcceleration; 338 protected Vector3 m_lastAcceleration;
329 protected Vector3 m_lastAngularVelocity; 339 protected Vector3 m_lastAngularVelocity;
330 protected int m_lastTerseSent; 340 protected int m_lastTerseSent;
341 protected float m_buoyancy = 0.0f;
331 342
332 /// <summary> 343 /// <summary>
333 /// Stores media texture data 344 /// Stores media texture data
@@ -380,7 +391,7 @@ namespace OpenSim.Region.Framework.Scenes
380 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 391 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
381 Quaternion rotationOffset, Vector3 offsetPosition) 392 Quaternion rotationOffset, Vector3 offsetPosition)
382 { 393 {
383 m_name = "Primitive"; 394 m_name = "Object";
384 395
385 Rezzed = DateTime.UtcNow; 396 Rezzed = DateTime.UtcNow;
386 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 397 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
@@ -436,7 +447,7 @@ namespace OpenSim.Region.Framework.Scenes
436 private uint _ownerMask = (uint)PermissionMask.All; 447 private uint _ownerMask = (uint)PermissionMask.All;
437 private uint _groupMask = (uint)PermissionMask.None; 448 private uint _groupMask = (uint)PermissionMask.None;
438 private uint _everyoneMask = (uint)PermissionMask.None; 449 private uint _everyoneMask = (uint)PermissionMask.None;
439 private uint _nextOwnerMask = (uint)PermissionMask.All; 450 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
440 private PrimFlags _flags = PrimFlags.None; 451 private PrimFlags _flags = PrimFlags.None;
441 private DateTime m_expires; 452 private DateTime m_expires;
442 private DateTime m_rezzed; 453 private DateTime m_rezzed;
@@ -535,12 +546,16 @@ namespace OpenSim.Region.Framework.Scenes
535 } 546 }
536 547
537 /// <value> 548 /// <value>
538 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 549 /// Get the inventory list
539 /// </value> 550 /// </value>
540 public TaskInventoryDictionary TaskInventory 551 public TaskInventoryDictionary TaskInventory
541 { 552 {
542 get { return m_inventory.Items; } 553 get {
543 set { m_inventory.Items = value; } 554 return m_inventory.Items;
555 }
556 set {
557 m_inventory.Items = value;
558 }
544 } 559 }
545 560
546 /// <summary> 561 /// <summary>
@@ -680,14 +695,12 @@ namespace OpenSim.Region.Framework.Scenes
680 set { m_LoopSoundSlavePrims = value; } 695 set { m_LoopSoundSlavePrims = value; }
681 } 696 }
682 697
683
684 public Byte[] TextureAnimation 698 public Byte[] TextureAnimation
685 { 699 {
686 get { return m_TextureAnimation; } 700 get { return m_TextureAnimation; }
687 set { m_TextureAnimation = value; } 701 set { m_TextureAnimation = value; }
688 } 702 }
689 703
690
691 public Byte[] ParticleSystem 704 public Byte[] ParticleSystem
692 { 705 {
693 get { return m_particleSystem; } 706 get { return m_particleSystem; }
@@ -724,9 +737,11 @@ namespace OpenSim.Region.Framework.Scenes
724 { 737 {
725 // If this is a linkset, we don't want the physics engine mucking up our group position here. 738 // If this is a linkset, we don't want the physics engine mucking up our group position here.
726 PhysicsActor actor = PhysActor; 739 PhysicsActor actor = PhysActor;
727 if (actor != null && _parentID == 0) 740 if (_parentID == 0)
728 { 741 {
729 m_groupPosition = actor.Position; 742 if (actor != null)
743 m_groupPosition = actor.Position;
744 return m_groupPosition;
730 } 745 }
731 746
732 if (IsAttachment) 747 if (IsAttachment)
@@ -736,12 +751,14 @@ namespace OpenSim.Region.Framework.Scenes
736 return sp.AbsolutePosition; 751 return sp.AbsolutePosition;
737 } 752 }
738 753
754 // use root prim's group position. Physics may have updated it
755 if (ParentGroup.RootPart != this)
756 m_groupPosition = ParentGroup.RootPart.GroupPosition;
739 return m_groupPosition; 757 return m_groupPosition;
740 } 758 }
741 set 759 set
742 { 760 {
743 m_groupPosition = value; 761 m_groupPosition = value;
744
745 PhysicsActor actor = PhysActor; 762 PhysicsActor actor = PhysActor;
746 if (actor != null) 763 if (actor != null)
747 { 764 {
@@ -761,25 +778,13 @@ namespace OpenSim.Region.Framework.Scenes
761 778
762 // Tell the physics engines that this prim changed. 779 // Tell the physics engines that this prim changed.
763 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 780 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
781
764 } 782 }
765 catch (Exception e) 783 catch (Exception e)
766 { 784 {
767 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 785 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
768 } 786 }
769 } 787 }
770
771 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
772 if (m_sitTargetAvatar != UUID.Zero)
773 {
774 if (m_parentGroup != null) // TODO can there be a SOP without a SOG?
775 {
776 ScenePresence avatar;
777 if (m_parentGroup.Scene.TryGetScenePresence(m_sitTargetAvatar, out avatar))
778 {
779 avatar.ParentPosition = GetWorldPosition();
780 }
781 }
782 }
783 } 788 }
784 } 789 }
785 790
@@ -788,7 +793,8 @@ namespace OpenSim.Region.Framework.Scenes
788 get { return m_offsetPosition; } 793 get { return m_offsetPosition; }
789 set 794 set
790 { 795 {
791 StoreUndoState(); 796 Vector3 oldpos = m_offsetPosition;
797 StoreUndoState(UndoType.STATE_PRIM_POSITION);
792 m_offsetPosition = value; 798 m_offsetPosition = value;
793 799
794 if (ParentGroup != null && !ParentGroup.IsDeleted) 800 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -803,7 +809,22 @@ namespace OpenSim.Region.Framework.Scenes
803 if (m_parentGroup.Scene != null) 809 if (m_parentGroup.Scene != null)
804 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 810 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
805 } 811 }
812
813 if (!m_parentGroup.m_dupeInProgress)
814 {
815 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
816 foreach (ScenePresence av in avs)
817 {
818 if (av.LinkedPrim == m_uuid)
819 {
820 Vector3 offset = (m_offsetPosition - oldpos);
821 av.OffsetPosition += offset;
822 av.SendAvatarDataToAllAgents();
823 }
824 }
825 }
806 } 826 }
827 TriggerScriptChangedEvent(Changed.POSITION);
807 } 828 }
808 } 829 }
809 830
@@ -845,7 +866,7 @@ namespace OpenSim.Region.Framework.Scenes
845 866
846 set 867 set
847 { 868 {
848 StoreUndoState(); 869 StoreUndoState(UndoType.STATE_PRIM_ROTATION);
849 m_rotationOffset = value; 870 m_rotationOffset = value;
850 871
851 PhysicsActor actor = PhysActor; 872 PhysicsActor actor = PhysActor;
@@ -929,7 +950,16 @@ namespace OpenSim.Region.Framework.Scenes
929 /// <summary></summary> 950 /// <summary></summary>
930 public Vector3 Acceleration 951 public Vector3 Acceleration
931 { 952 {
932 get { return m_acceleration; } 953 get
954 {
955 PhysicsActor actor = PhysActor;
956 if (actor != null)
957 {
958 m_acceleration = actor.Acceleration;
959 }
960 return m_acceleration;
961 }
962
933 set { m_acceleration = value; } 963 set { m_acceleration = value; }
934 } 964 }
935 965
@@ -1020,7 +1050,7 @@ namespace OpenSim.Region.Framework.Scenes
1020 get { return m_shape.Scale; } 1050 get { return m_shape.Scale; }
1021 set 1051 set
1022 { 1052 {
1023 StoreUndoState(); 1053 StoreUndoState(UndoType.STATE_PRIM_SCALE);
1024 if (m_shape != null) 1054 if (m_shape != null)
1025 { 1055 {
1026 m_shape.Scale = value; 1056 m_shape.Scale = value;
@@ -1091,7 +1121,7 @@ namespace OpenSim.Region.Framework.Scenes
1091 if (IsAttachment) 1121 if (IsAttachment)
1092 return GroupPosition; 1122 return GroupPosition;
1093 1123
1094 return m_offsetPosition + m_groupPosition; 1124 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1095 } 1125 }
1096 } 1126 }
1097 1127
@@ -1251,6 +1281,13 @@ namespace OpenSim.Region.Framework.Scenes
1251 _flags = value; 1281 _flags = value;
1252 } 1282 }
1253 } 1283 }
1284
1285 [XmlIgnore]
1286 public bool IsOccupied // KF If an av is sittingon this prim
1287 {
1288 get { return m_occupied; }
1289 set { m_occupied = value; }
1290 }
1254 1291
1255 1292
1256 public UUID SitTargetAvatar 1293 public UUID SitTargetAvatar
@@ -1310,6 +1347,19 @@ namespace OpenSim.Region.Framework.Scenes
1310 set { m_collisionSoundVolume = value; } 1347 set { m_collisionSoundVolume = value; }
1311 } 1348 }
1312 1349
1350 public float Buoyancy
1351 {
1352 get { return m_buoyancy; }
1353 set
1354 {
1355 m_buoyancy = value;
1356 if (PhysActor != null)
1357 {
1358 PhysActor.Buoyancy = value;
1359 }
1360 }
1361 }
1362
1313 #endregion Public Properties with only Get 1363 #endregion Public Properties with only Get
1314 1364
1315 #region Private Methods 1365 #region Private Methods
@@ -1326,14 +1376,6 @@ namespace OpenSim.Region.Framework.Scenes
1326 } 1376 }
1327 } 1377 }
1328 1378
1329 /// <summary>
1330 /// Clear all pending updates of parts to clients
1331 /// </summary>
1332 private void ClearUpdateSchedule()
1333 {
1334 m_updateFlag = 0;
1335 }
1336
1337 private void SendObjectPropertiesToClient(UUID AgentID) 1379 private void SendObjectPropertiesToClient(UUID AgentID)
1338 { 1380 {
1339 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1381 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1584,15 +1626,22 @@ namespace OpenSim.Region.Framework.Scenes
1584 // or flexible 1626 // or flexible
1585 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible)) 1627 if (!isPhantom && !IsAttachment && !(Shape.PathCurve == (byte) Extrusion.Flexible))
1586 { 1628 {
1587 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape( 1629 try
1588 LocalId, 1630 {
1589 string.Format("{0}/{1}", Name, UUID), 1631 PhysActor = m_parentGroup.Scene.PhysicsScene.AddPrimShape(
1590 Shape, 1632 string.Format("{0}/{1}", Name, UUID),
1591 AbsolutePosition, 1633 Shape,
1592 Scale, 1634 AbsolutePosition,
1593 RotationOffset, 1635 Scale,
1594 RigidBody); 1636 RotationOffset,
1595 1637 RigidBody);
1638 PhysActor.SetMaterial(Material);
1639 }
1640 catch
1641 {
1642 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid);
1643 PhysActor = null;
1644 }
1596 // Basic Physics returns null.. joy joy joy. 1645 // Basic Physics returns null.. joy joy joy.
1597 if (PhysActor != null) 1646 if (PhysActor != null)
1598 { 1647 {
@@ -1619,7 +1668,7 @@ namespace OpenSim.Region.Framework.Scenes
1619 { 1668 {
1620 m_redo.Clear(); 1669 m_redo.Clear();
1621 } 1670 }
1622 StoreUndoState(); 1671 StoreUndoState(UndoType.STATE_ALL);
1623 } 1672 }
1624 1673
1625 public byte ConvertScriptUintToByte(uint indata) 1674 public byte ConvertScriptUintToByte(uint indata)
@@ -1688,6 +1737,9 @@ namespace OpenSim.Region.Framework.Scenes
1688 1737
1689 // Move afterwards ResetIDs as it clears the localID 1738 // Move afterwards ResetIDs as it clears the localID
1690 dupe.LocalId = localID; 1739 dupe.LocalId = localID;
1740 if(dupe.PhysActor != null)
1741 dupe.PhysActor.LocalID = localID;
1742
1691 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1743 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1692 dupe._lastOwnerID = OwnerID; 1744 dupe._lastOwnerID = OwnerID;
1693 1745
@@ -1731,7 +1783,7 @@ namespace OpenSim.Region.Framework.Scenes
1731 PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); 1783 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1732 part.Shape = shape; 1784 part.Shape = shape;
1733 1785
1734 part.Name = "Primitive"; 1786 part.Name = "Object";
1735 part._ownerID = UUID.Random(); 1787 part._ownerID = UUID.Random();
1736 1788
1737 return part; 1789 return part;
@@ -2084,19 +2136,17 @@ namespace OpenSim.Region.Framework.Scenes
2084 public Vector3 GetWorldPosition() 2136 public Vector3 GetWorldPosition()
2085 { 2137 {
2086 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2138 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2087
2088 Vector3 axPos = OffsetPosition; 2139 Vector3 axPos = OffsetPosition;
2089
2090 axPos *= parentRot; 2140 axPos *= parentRot;
2091 Vector3 translationOffsetPosition = axPos; 2141 Vector3 translationOffsetPosition = axPos;
2092 2142 if(_parentID == 0)
2093// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name); 2143 {
2094 2144 return GroupPosition;
2095 Vector3 worldPos = GroupPosition + translationOffsetPosition; 2145 }
2096 2146 else
2097// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name); 2147 {
2098 2148 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2099 return worldPos; 2149 }
2100 } 2150 }
2101 2151
2102 /// <summary> 2152 /// <summary>
@@ -2753,17 +2803,18 @@ namespace OpenSim.Region.Framework.Scenes
2753 //Trys to fetch sound id from prim's inventory. 2803 //Trys to fetch sound id from prim's inventory.
2754 //Prim's inventory doesn't support non script items yet 2804 //Prim's inventory doesn't support non script items yet
2755 2805
2756 lock (TaskInventory) 2806 TaskInventory.LockItemsForRead(true);
2807
2808 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2757 { 2809 {
2758 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2810 if (item.Value.Name == sound)
2759 { 2811 {
2760 if (item.Value.Name == sound) 2812 soundID = item.Value.ItemID;
2761 { 2813 break;
2762 soundID = item.Value.ItemID;
2763 break;
2764 }
2765 } 2814 }
2766 } 2815 }
2816
2817 TaskInventory.LockItemsForRead(false);
2767 } 2818 }
2768 2819
2769 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2820 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2823,7 +2874,7 @@ namespace OpenSim.Region.Framework.Scenes
2823 /// <param name="scale"></param> 2874 /// <param name="scale"></param>
2824 public void Resize(Vector3 scale) 2875 public void Resize(Vector3 scale)
2825 { 2876 {
2826 StoreUndoState(); 2877 StoreUndoState(UndoType.STATE_PRIM_SCALE);
2827 m_shape.Scale = scale; 2878 m_shape.Scale = scale;
2828 2879
2829 ParentGroup.HasGroupChanged = true; 2880 ParentGroup.HasGroupChanged = true;
@@ -2832,38 +2883,7 @@ namespace OpenSim.Region.Framework.Scenes
2832 2883
2833 public void RotLookAt(Quaternion target, float strength, float damping) 2884 public void RotLookAt(Quaternion target, float strength, float damping)
2834 { 2885 {
2835 rotLookAt(target, strength, damping); 2886 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2836 }
2837
2838 public void rotLookAt(Quaternion target, float strength, float damping)
2839 {
2840 if (IsAttachment)
2841 {
2842 /*
2843 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2844 if (avatar != null)
2845 {
2846 Rotate the Av?
2847 } */
2848 }
2849 else
2850 {
2851 APIDDamp = damping;
2852 APIDStrength = strength;
2853 APIDTarget = target;
2854 }
2855 }
2856
2857 public void startLookAt(Quaternion rot, float damp, float strength)
2858 {
2859 APIDDamp = damp;
2860 APIDStrength = strength;
2861 APIDTarget = rot;
2862 }
2863
2864 public void stopLookAt()
2865 {
2866 APIDTarget = Quaternion.Identity;
2867 } 2887 }
2868 2888
2869 /// <summary> 2889 /// <summary>
@@ -2875,7 +2895,10 @@ namespace OpenSim.Region.Framework.Scenes
2875 2895
2876 if (m_parentGroup != null) 2896 if (m_parentGroup != null)
2877 { 2897 {
2878 m_parentGroup.QueueForUpdateCheck(); 2898 if (!m_parentGroup.areUpdatesSuspended)
2899 {
2900 m_parentGroup.QueueForUpdateCheck();
2901 }
2879 } 2902 }
2880 2903
2881 int timeNow = Util.UnixTimeSinceEpoch(); 2904 int timeNow = Util.UnixTimeSinceEpoch();
@@ -3092,8 +3115,8 @@ namespace OpenSim.Region.Framework.Scenes
3092 { 3115 {
3093 const float ROTATION_TOLERANCE = 0.01f; 3116 const float ROTATION_TOLERANCE = 0.01f;
3094 const float VELOCITY_TOLERANCE = 0.001f; 3117 const float VELOCITY_TOLERANCE = 0.001f;
3095 const float POSITION_TOLERANCE = 0.05f; 3118 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3096 const int TIME_MS_TOLERANCE = 3000; 3119 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3097 3120
3098 if (m_updateFlag == 1) 3121 if (m_updateFlag == 1)
3099 { 3122 {
@@ -3107,7 +3130,7 @@ namespace OpenSim.Region.Framework.Scenes
3107 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3130 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3108 { 3131 {
3109 AddTerseUpdateToAllAvatars(); 3132 AddTerseUpdateToAllAvatars();
3110 ClearUpdateSchedule(); 3133
3111 3134
3112 // This causes the Scene to 'poll' physical objects every couple of frames 3135 // This causes the Scene to 'poll' physical objects every couple of frames
3113 // bad, so it's been replaced by an event driven method. 3136 // bad, so it's been replaced by an event driven method.
@@ -3125,16 +3148,18 @@ namespace OpenSim.Region.Framework.Scenes
3125 m_lastAngularVelocity = AngularVelocity; 3148 m_lastAngularVelocity = AngularVelocity;
3126 m_lastTerseSent = Environment.TickCount; 3149 m_lastTerseSent = Environment.TickCount;
3127 } 3150 }
3151 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3152 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3128 } 3153 }
3129 else 3154 else
3130 { 3155 {
3131 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3156 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3132 { 3157 {
3133 AddFullUpdateToAllAvatars(); 3158 AddFullUpdateToAllAvatars();
3134 ClearUpdateSchedule(); 3159 m_updateFlag = 0; //Same here
3135 } 3160 }
3136 } 3161 }
3137 ClearUpdateSchedule(); 3162 m_updateFlag = 0;
3138 } 3163 }
3139 3164
3140 /// <summary> 3165 /// <summary>
@@ -3162,17 +3187,16 @@ namespace OpenSim.Region.Framework.Scenes
3162 if (!UUID.TryParse(sound, out soundID)) 3187 if (!UUID.TryParse(sound, out soundID))
3163 { 3188 {
3164 // search sound file from inventory 3189 // search sound file from inventory
3165 lock (TaskInventory) 3190 TaskInventory.LockItemsForRead(true);
3191 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3166 { 3192 {
3167 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3193 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3168 { 3194 {
3169 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3195 soundID = item.Value.ItemID;
3170 { 3196 break;
3171 soundID = item.Value.ItemID;
3172 break;
3173 }
3174 } 3197 }
3175 } 3198 }
3199 TaskInventory.LockItemsForRead(false);
3176 } 3200 }
3177 3201
3178 if (soundID == UUID.Zero) 3202 if (soundID == UUID.Zero)
@@ -3275,14 +3299,6 @@ namespace OpenSim.Region.Framework.Scenes
3275 STATUS_ROTATE_Z = rotate; 3299 STATUS_ROTATE_Z = rotate;
3276 } 3300 }
3277 3301
3278 public void SetBuoyancy(float fvalue)
3279 {
3280 if (PhysActor != null)
3281 {
3282 PhysActor.Buoyancy = fvalue;
3283 }
3284 }
3285
3286 public void SetDieAtEdge(bool p) 3302 public void SetDieAtEdge(bool p)
3287 { 3303 {
3288 if (m_parentGroup == null) 3304 if (m_parentGroup == null)
@@ -3602,7 +3618,7 @@ namespace OpenSim.Region.Framework.Scenes
3602 3618
3603 public void StopLookAt() 3619 public void StopLookAt()
3604 { 3620 {
3605 m_parentGroup.stopLookAt(); 3621 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3606 3622
3607 m_parentGroup.ScheduleGroupForTerseUpdate(); 3623 m_parentGroup.ScheduleGroupForTerseUpdate();
3608 } 3624 }
@@ -3629,10 +3645,9 @@ namespace OpenSim.Region.Framework.Scenes
3629 m_parentGroup.ScheduleGroupForTerseUpdate(); 3645 m_parentGroup.ScheduleGroupForTerseUpdate();
3630 //m_parentGroup.ScheduleGroupForFullUpdate(); 3646 //m_parentGroup.ScheduleGroupForFullUpdate();
3631 } 3647 }
3632 3648 public void StoreUndoState(UndoType type)
3633 public void StoreUndoState()
3634 { 3649 {
3635 if (!Undoing) 3650 if (!Undoing && (m_parentGroup == null || m_parentGroup.RootPart == null || !m_parentGroup.RootPart.Undoing))
3636 { 3651 {
3637 if (!IgnoreUndoUpdate) 3652 if (!IgnoreUndoUpdate)
3638 { 3653 {
@@ -3643,17 +3658,25 @@ namespace OpenSim.Region.Framework.Scenes
3643 if (m_undo.Count > 0) 3658 if (m_undo.Count > 0)
3644 { 3659 {
3645 UndoState last = m_undo.Peek(); 3660 UndoState last = m_undo.Peek();
3646 if (last != null) 3661
3647 {
3648 if (last.Compare(this))
3649 return;
3650 }
3651 } 3662 }
3652 3663
3653 if (m_parentGroup.GetSceneMaxUndo() > 0) 3664 if (m_parentGroup.GetSceneMaxUndo() > 0)
3654 { 3665 {
3655 UndoState nUndo = new UndoState(this); 3666 UndoState lastUndo = m_undo.Peek();
3656 3667
3668 UndoState nUndo = new UndoState(this, type);
3669
3670 if (lastUndo != null)
3671 {
3672 TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated);
3673 if (ts.TotalMilliseconds < 500)
3674 {
3675 //Delete the last entry since it was less than 500 milliseconds ago
3676 nUndo.Merge(lastUndo);
3677 m_undo.Pop();
3678 }
3679 }
3657 m_undo.Push(nUndo); 3680 m_undo.Push(nUndo);
3658 } 3681 }
3659 3682
@@ -4130,11 +4153,13 @@ namespace OpenSim.Region.Framework.Scenes
4130 if (m_undo.Count > 0) 4153 if (m_undo.Count > 0)
4131 { 4154 {
4132 UndoState nUndo = null; 4155 UndoState nUndo = null;
4156 UndoState goback = m_undo.Pop();
4133 if (m_parentGroup.GetSceneMaxUndo() > 0) 4157 if (m_parentGroup.GetSceneMaxUndo() > 0)
4134 { 4158 {
4135 nUndo = new UndoState(this); 4159 nUndo = new UndoState(this, goback.Type);
4136 } 4160 }
4137 UndoState goback = m_undo.Pop(); 4161
4162
4138 if (goback != null) 4163 if (goback != null)
4139 { 4164 {
4140 goback.PlaybackState(this); 4165 goback.PlaybackState(this);
@@ -4149,13 +4174,13 @@ namespace OpenSim.Region.Framework.Scenes
4149 { 4174 {
4150 lock (m_redo) 4175 lock (m_redo)
4151 { 4176 {
4177 UndoState gofwd = m_redo.Pop();
4152 if (m_parentGroup.GetSceneMaxUndo() > 0) 4178 if (m_parentGroup.GetSceneMaxUndo() > 0)
4153 { 4179 {
4154 UndoState nUndo = new UndoState(this); 4180 UndoState nUndo = new UndoState(this, gofwd.Type);
4155 4181
4156 m_undo.Push(nUndo); 4182 m_undo.Push(nUndo);
4157 } 4183 }
4158 UndoState gofwd = m_redo.Pop();
4159 if (gofwd != null) 4184 if (gofwd != null)
4160 gofwd.PlayfwdState(this); 4185 gofwd.PlayfwdState(this);
4161 } 4186 }
@@ -4420,6 +4445,7 @@ namespace OpenSim.Region.Framework.Scenes
4420 Scale, 4445 Scale,
4421 RotationOffset, 4446 RotationOffset,
4422 UsePhysics); 4447 UsePhysics);
4448 PhysActor.SetMaterial(Material);
4423 4449
4424 pa = PhysActor; 4450 pa = PhysActor;
4425 if (pa != null) 4451 if (pa != null)
@@ -4604,8 +4630,9 @@ namespace OpenSim.Region.Framework.Scenes
4604 { 4630 {
4605 m_shape.TextureEntry = textureEntry; 4631 m_shape.TextureEntry = textureEntry;
4606 TriggerScriptChangedEvent(Changed.TEXTURE); 4632 TriggerScriptChangedEvent(Changed.TEXTURE);
4607 4633 m_updateFlag = 1;
4608 ParentGroup.HasGroupChanged = true; 4634 ParentGroup.HasGroupChanged = true;
4635
4609 //This is madness.. 4636 //This is madness..
4610 //ParentGroup.ScheduleGroupForFullUpdate(); 4637 //ParentGroup.ScheduleGroupForFullUpdate();
4611 //This is sparta 4638 //This is sparta
@@ -4838,5 +4865,17 @@ namespace OpenSim.Region.Framework.Scenes
4838 Color color = Color; 4865 Color color = Color;
4839 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4866 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4840 } 4867 }
4868
4869 public void ResetOwnerChangeFlag()
4870 {
4871 List<UUID> inv = Inventory.GetInventoryList();
4872
4873 foreach (UUID itemID in inv)
4874 {
4875 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4876 item.OwnerChanged = false;
4877 Inventory.UpdateInventoryItem(item, false, false);
4878 }
4879 }
4841 } 4880 }
4842} 4881}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 3b60f8c..56680df 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
@@ -617,6 +803,9 @@ namespace OpenSim.Region.Framework.Scenes
617 string xmlData = Utils.BytesToString(rezAsset.Data); 803 string xmlData = Utils.BytesToString(rezAsset.Data);
618 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 804 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
619 805
806 group.RootPart.AttachPoint = group.RootPart.Shape.State;
807 group.RootPart.AttachOffset = group.AbsolutePosition;
808
620 group.ResetIDs(); 809 group.ResetIDs();
621 810
622 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 811 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -691,8 +880,9 @@ namespace OpenSim.Region.Framework.Scenes
691 880
692 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 881 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
693 { 882 {
694 TaskInventoryItem it = GetInventoryItem(item.ItemID); 883 m_items.LockItemsForWrite(true);
695 if (it != null) 884
885 if (m_items.ContainsKey(item.ItemID))
696 { 886 {
697// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 887// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
698 888
@@ -705,14 +895,10 @@ namespace OpenSim.Region.Framework.Scenes
705 item.GroupID = m_part.GroupID; 895 item.GroupID = m_part.GroupID;
706 896
707 if (item.AssetID == UUID.Zero) 897 if (item.AssetID == UUID.Zero)
708 item.AssetID = it.AssetID; 898 item.AssetID = m_items[item.ItemID].AssetID;
709 899
710 lock (m_items) 900 m_items[item.ItemID] = item;
711 { 901 m_inventorySerial++;
712 m_items[item.ItemID] = item;
713 m_inventorySerial++;
714 }
715
716 if (fireScriptEvents) 902 if (fireScriptEvents)
717 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 903 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
718 904
@@ -721,7 +907,7 @@ namespace OpenSim.Region.Framework.Scenes
721 HasInventoryChanged = true; 907 HasInventoryChanged = true;
722 m_part.ParentGroup.HasGroupChanged = true; 908 m_part.ParentGroup.HasGroupChanged = true;
723 } 909 }
724 910 m_items.LockItemsForWrite(false);
725 return true; 911 return true;
726 } 912 }
727 else 913 else
@@ -732,8 +918,9 @@ namespace OpenSim.Region.Framework.Scenes
732 item.ItemID, m_part.Name, m_part.UUID, 918 item.ItemID, m_part.Name, m_part.UUID,
733 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 919 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
734 } 920 }
735 return false; 921 m_items.LockItemsForWrite(false);
736 922
923 return false;
737 } 924 }
738 925
739 /// <summary> 926 /// <summary>
@@ -744,107 +931,68 @@ namespace OpenSim.Region.Framework.Scenes
744 /// in this prim's inventory.</returns> 931 /// in this prim's inventory.</returns>
745 public int RemoveInventoryItem(UUID itemID) 932 public int RemoveInventoryItem(UUID itemID)
746 { 933 {
747 TaskInventoryItem item = GetInventoryItem(itemID); 934 m_items.LockItemsForRead(true);
748 if (item != null) 935
936 if (m_items.ContainsKey(itemID))
749 { 937 {
750 int type = m_items[itemID].InvType; 938 int type = m_items[itemID].InvType;
939 m_items.LockItemsForRead(false);
751 if (type == 10) // Script 940 if (type == 10) // Script
752 { 941 {
753 m_part.RemoveScriptEvents(itemID);
754 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 942 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
755 } 943 }
944 m_items.LockItemsForWrite(true);
756 m_items.Remove(itemID); 945 m_items.Remove(itemID);
946 m_items.LockItemsForWrite(false);
757 m_inventorySerial++; 947 m_inventorySerial++;
758 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 948 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
759 949
760 HasInventoryChanged = true; 950 HasInventoryChanged = true;
761 m_part.ParentGroup.HasGroupChanged = true; 951 m_part.ParentGroup.HasGroupChanged = true;
762 952
763 if (!ContainsScripts()) 953 int scriptcount = 0;
954 m_items.LockItemsForRead(true);
955 foreach (TaskInventoryItem item in m_items.Values)
956 {
957 if (item.Type == 10)
958 {
959 scriptcount++;
960 }
961 }
962 m_items.LockItemsForRead(false);
963
964
965 if (scriptcount <= 0)
966 {
764 m_part.RemFlag(PrimFlags.Scripted); 967 m_part.RemFlag(PrimFlags.Scripted);
968 }
765 969
766 m_part.ScheduleFullUpdate(); 970 m_part.ScheduleFullUpdate();
767 971
768 return type; 972 return type;
769
770 } 973 }
771 else 974 else
772 { 975 {
976 m_items.LockItemsForRead(false);
773 m_log.ErrorFormat( 977 m_log.ErrorFormat(
774 "[PRIM INVENTORY]: " + 978 "[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", 979 "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, 980 itemID, m_part.Name, m_part.UUID);
777 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
778 } 981 }
779 982
780 return -1; 983 return -1;
781 } 984 }
782 985
783 private bool CreateInventoryFile() 986 private bool CreateInventoryFileName()
784 { 987 {
785 if (m_inventoryFileName == String.Empty || 988 if (m_inventoryFileName == String.Empty ||
786 m_inventoryFileNameSerial < m_inventorySerial) 989 m_inventoryFileNameSerial < m_inventorySerial)
787 { 990 {
788 // Something changed, we need to create a new file
789 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 991 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
790 m_inventoryFileNameSerial = m_inventorySerial; 992 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; 993 return true;
845 } 994 }
846 995
847 // No need to recreate, the existing file is fine
848 return false; 996 return false;
849 } 997 }
850 998
@@ -854,26 +1002,99 @@ namespace OpenSim.Region.Framework.Scenes
854 /// <param name="xferManager"></param> 1002 /// <param name="xferManager"></param>
855 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 1003 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
856 { 1004 {
857 CreateInventoryFile(); 1005 bool changed = CreateInventoryFileName();
1006
1007 bool includeAssets = false;
1008 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1009 includeAssets = true;
1010
1011 if (m_inventoryPrivileged != includeAssets)
1012 changed = true;
1013
1014 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1015
1016 Items.LockItemsForRead(true);
858 1017
859 if (m_inventorySerial == 0) // No inventory 1018 if (m_inventorySerial == 0) // No inventory
860 { 1019 {
861 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1020 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1021 Items.LockItemsForRead(false);
862 return; 1022 return;
863 } 1023 }
864 1024
865 // In principle, we should only do the rest if the inventory changed; 1025 if (!changed)
866 // by sending m_inventorySerial to the client, it ought to know 1026 {
867 // that nothing changed and that it doesn't need to request the file. 1027 if (m_inventoryFileData.Length > 2)
868 // Unfortunately, it doesn't look like the client optimizes this; 1028 {
869 // the client seems to always come back and request the Xfer, 1029 xferManager.AddNewFile(m_inventoryFileName,
870 // no matter what value m_inventorySerial has. 1030 m_inventoryFileData);
1031 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1032 Util.StringToBytes256(m_inventoryFileName));
1033
1034 Items.LockItemsForRead(false);
1035 return;
1036 }
1037 }
1038
1039 m_inventoryPrivileged = includeAssets;
1040
1041 foreach (TaskInventoryItem item in m_items.Values)
1042 {
1043 UUID ownerID = item.OwnerID;
1044 uint everyoneMask = 0;
1045 uint baseMask = item.BasePermissions;
1046 uint ownerMask = item.CurrentPermissions;
1047 uint groupMask = item.GroupPermissions;
1048
1049 invString.AddItemStart();
1050 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1051 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1052
1053 invString.AddPermissionsStart();
1054
1055 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1056 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1057 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1058 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1059 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1060
1061 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1062 invString.AddNameValueLine("owner_id", ownerID.ToString());
1063
1064 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1065
1066 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1067 invString.AddSectionEnd();
1068
1069 if (includeAssets)
1070 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1071 else
1072 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1073 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
1074 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
1075 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1076
1077 invString.AddSaleStart();
1078 invString.AddNameValueLine("sale_type", "not");
1079 invString.AddNameValueLine("sale_price", "0");
1080 invString.AddSectionEnd();
1081
1082 invString.AddNameValueLine("name", item.Name + "|");
1083 invString.AddNameValueLine("desc", item.Description + "|");
1084
1085 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1086 invString.AddSectionEnd();
1087 }
1088
1089 Items.LockItemsForRead(false);
1090
1091 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
871 1092
872 if (m_inventoryFileData.Length > 2) 1093 if (m_inventoryFileData.Length > 2)
873 // Add the file for Xfer 1094 {
874 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 1095 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1096 }
875 1097
876 // Tell the client we're ready to Xfer the file
877 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, 1098 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
878 Util.StringToBytes256(m_inventoryFileName)); 1099 Util.StringToBytes256(m_inventoryFileName));
879 } 1100 }
@@ -886,10 +1107,11 @@ namespace OpenSim.Region.Framework.Scenes
886 { 1107 {
887 if (HasInventoryChanged) 1108 if (HasInventoryChanged)
888 { 1109 {
889 HasInventoryChanged = false; 1110 Items.LockItemsForRead(true);
890 List<TaskInventoryItem> items = GetInventoryItems(); 1111 datastore.StorePrimInventory(m_part.UUID, Items.Values);
891 datastore.StorePrimInventory(m_part.UUID, items); 1112 Items.LockItemsForRead(false);
892 1113
1114 HasInventoryChanged = false;
893 } 1115 }
894 } 1116 }
895 1117
@@ -956,82 +1178,63 @@ namespace OpenSim.Region.Framework.Scenes
956 { 1178 {
957 uint mask=0x7fffffff; 1179 uint mask=0x7fffffff;
958 1180
959 lock (m_items) 1181 foreach (TaskInventoryItem item in m_items.Values)
960 { 1182 {
961 foreach (TaskInventoryItem item in m_items.Values) 1183 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1184 mask &= ~((uint)PermissionMask.Copy >> 13);
1185 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1186 mask &= ~((uint)PermissionMask.Transfer >> 13);
1187 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1188 mask &= ~((uint)PermissionMask.Modify >> 13);
1189
1190 if (item.InvType == (int)InventoryType.Object)
962 { 1191 {
963 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1192 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
964 mask &= ~((uint)PermissionMask.Copy >> 13); 1193 mask &= ~((uint)PermissionMask.Copy >> 13);
965 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1194 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
966 mask &= ~((uint)PermissionMask.Transfer >> 13); 1195 mask &= ~((uint)PermissionMask.Transfer >> 13);
967 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1196 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
968 mask &= ~((uint)PermissionMask.Modify >> 13); 1197 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 } 1198 }
1199
1200 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1201 mask &= ~(uint)PermissionMask.Copy;
1202 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1203 mask &= ~(uint)PermissionMask.Transfer;
1204 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1205 mask &= ~(uint)PermissionMask.Modify;
996 } 1206 }
997
998 return mask; 1207 return mask;
999 } 1208 }
1000 1209
1001 public void ApplyNextOwnerPermissions() 1210 public void ApplyNextOwnerPermissions()
1002 { 1211 {
1003 lock (m_items) 1212 foreach (TaskInventoryItem item in m_items.Values)
1004 { 1213 {
1005 foreach (TaskInventoryItem item in m_items.Values) 1214 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1006 { 1215 {
1007 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1216 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1008 { 1217 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1009 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1218 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1010 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1219 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1011 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1220 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1012 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1221 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 } 1222 }
1223 item.OwnerChanged = true;
1224 item.CurrentPermissions &= item.NextPermissions;
1225 item.BasePermissions &= item.NextPermissions;
1226 item.EveryonePermissions &= item.NextPermissions;
1227 item.PermsMask = 0;
1228 item.PermsGranter = UUID.Zero;
1023 } 1229 }
1024 } 1230 }
1025 1231
1026 public void ApplyGodPermissions(uint perms) 1232 public void ApplyGodPermissions(uint perms)
1027 { 1233 {
1028 lock (m_items) 1234 foreach (TaskInventoryItem item in m_items.Values)
1029 { 1235 {
1030 foreach (TaskInventoryItem item in m_items.Values) 1236 item.CurrentPermissions = perms;
1031 { 1237 item.BasePermissions = perms;
1032 item.CurrentPermissions = perms;
1033 item.BasePermissions = perms;
1034 }
1035 } 1238 }
1036 m_inventorySerial++; 1239 m_inventorySerial++;
1037 HasInventoryChanged = true; 1240 HasInventoryChanged = true;
@@ -1039,17 +1242,13 @@ namespace OpenSim.Region.Framework.Scenes
1039 1242
1040 public bool ContainsScripts() 1243 public bool ContainsScripts()
1041 { 1244 {
1042 lock (m_items) 1245 foreach (TaskInventoryItem item in m_items.Values)
1043 { 1246 {
1044 foreach (TaskInventoryItem item in m_items.Values) 1247 if (item.InvType == (int)InventoryType.LSL)
1045 { 1248 {
1046 if (item.InvType == (int)InventoryType.LSL) 1249 return true;
1047 {
1048 return true;
1049 }
1050 } 1250 }
1051 } 1251 }
1052
1053 return false; 1252 return false;
1054 } 1253 }
1055 1254
@@ -1057,11 +1256,8 @@ namespace OpenSim.Region.Framework.Scenes
1057 { 1256 {
1058 List<UUID> ret = new List<UUID>(); 1257 List<UUID> ret = new List<UUID>();
1059 1258
1060 lock (m_items) 1259 foreach (TaskInventoryItem item in m_items.Values)
1061 { 1260 ret.Add(item.ItemID);
1062 foreach (TaskInventoryItem item in m_items.Values)
1063 ret.Add(item.ItemID);
1064 }
1065 1261
1066 return ret; 1262 return ret;
1067 } 1263 }
@@ -1092,6 +1288,11 @@ namespace OpenSim.Region.Framework.Scenes
1092 1288
1093 public Dictionary<UUID, string> GetScriptStates() 1289 public Dictionary<UUID, string> GetScriptStates()
1094 { 1290 {
1291 return GetScriptStates(false);
1292 }
1293
1294 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1295 {
1095 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1296 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1096 1297
1097 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1298 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1102,25 +1303,35 @@ namespace OpenSim.Region.Framework.Scenes
1102 if (engines == null) // No engine at all 1303 if (engines == null) // No engine at all
1103 return ret; 1304 return ret;
1104 1305
1105 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1306 Items.LockItemsForRead(true);
1106 1307 foreach (TaskInventoryItem item in m_items.Values)
1107 foreach (TaskInventoryItem item in scripts)
1108 { 1308 {
1109 foreach (IScriptModule e in engines) 1309 if (item.InvType == (int)InventoryType.LSL)
1110 { 1310 {
1111 if (e != null) 1311 foreach (IScriptModule e in engines)
1112 { 1312 {
1113 string n = e.GetXMLState(item.ItemID); 1313 if (e != null)
1114 if (n != String.Empty)
1115 { 1314 {
1116 if (!ret.ContainsKey(item.ItemID)) 1315 string n = e.GetXMLState(item.ItemID);
1117 ret[item.ItemID] = n; 1316 if (n != String.Empty)
1118 break; 1317 {
1318 if (oldIDs)
1319 {
1320 if (!ret.ContainsKey(item.OldItemID))
1321 ret[item.OldItemID] = n;
1322 }
1323 else
1324 {
1325 if (!ret.ContainsKey(item.ItemID))
1326 ret[item.ItemID] = n;
1327 }
1328 break;
1329 }
1119 } 1330 }
1120 } 1331 }
1121 } 1332 }
1122 } 1333 }
1123 1334 Items.LockItemsForRead(false);
1124 return ret; 1335 return ret;
1125 } 1336 }
1126 1337
@@ -1130,21 +1341,27 @@ namespace OpenSim.Region.Framework.Scenes
1130 if (engines == null) 1341 if (engines == null)
1131 return; 1342 return;
1132 1343
1133 List<TaskInventoryItem> scripts = GetInventoryScripts();
1134 1344
1135 foreach (TaskInventoryItem item in scripts) 1345 Items.LockItemsForRead(true);
1346
1347 foreach (TaskInventoryItem item in m_items.Values)
1136 { 1348 {
1137 foreach (IScriptModule engine in engines) 1349 if (item.InvType == (int)InventoryType.LSL)
1138 { 1350 {
1139 if (engine != null) 1351 foreach (IScriptModule engine in engines)
1140 { 1352 {
1141 if (item.OwnerChanged) 1353 if (engine != null)
1142 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1354 {
1143 item.OwnerChanged = false; 1355 if (item.OwnerChanged)
1144 engine.ResumeScript(item.ItemID); 1356 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1357 item.OwnerChanged = false;
1358 engine.ResumeScript(item.ItemID);
1359 }
1145 } 1360 }
1146 } 1361 }
1147 } 1362 }
1363
1364 Items.LockItemsForRead(false);
1148 } 1365 }
1149 } 1366 }
1150} 1367}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 83b761c..d2f84e3 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;
@@ -253,7 +274,9 @@ namespace OpenSim.Region.Framework.Scenes
253 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 274 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
254 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 275 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
255 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 276 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
256 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 277 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
278 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
279 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
257 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 280 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
258 } 281 }
259 282
@@ -460,7 +483,8 @@ namespace OpenSim.Region.Framework.Scenes
460 get 483 get
461 { 484 {
462 PhysicsActor actor = m_physicsActor; 485 PhysicsActor actor = m_physicsActor;
463 if (actor != null) 486// if (actor != null)
487 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
464 m_pos = actor.Position; 488 m_pos = actor.Position;
465 else 489 else
466 { 490 {
@@ -482,7 +506,7 @@ namespace OpenSim.Region.Framework.Scenes
482 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 506 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
483 if (part != null) 507 if (part != null)
484 { 508 {
485 return m_parentPosition + (m_pos * part.GetWorldRotation()); 509 return part.AbsolutePosition + (m_pos * part.GetWorldRotation());
486 } 510 }
487 else 511 else
488 { 512 {
@@ -509,7 +533,8 @@ namespace OpenSim.Region.Framework.Scenes
509 } 533 }
510 } 534 }
511 535
512 m_pos = value; 536 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
537 m_pos = value;
513 m_parentPosition = Vector3.Zero; 538 m_parentPosition = Vector3.Zero;
514 } 539 }
515 } 540 }
@@ -553,10 +578,39 @@ namespace OpenSim.Region.Framework.Scenes
553 } 578 }
554 } 579 }
555 580
581 public Quaternion OffsetRotation
582 {
583 get { return m_offsetRotation; }
584 set { m_offsetRotation = value; }
585 }
586
556 public Quaternion Rotation 587 public Quaternion Rotation
557 { 588 {
558 get { return m_bodyRot; } 589 get {
559 set { m_bodyRot = value; } 590 if (m_parentID != 0)
591 {
592 if (m_offsetRotation != null)
593 {
594 return m_offsetRotation;
595 }
596 else
597 {
598 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
599 }
600
601 }
602 else
603 {
604 return m_bodyRot;
605 }
606 }
607 set {
608 m_bodyRot = value;
609 if (m_parentID != 0)
610 {
611 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
612 }
613 }
560 } 614 }
561 615
562 public Quaternion PreviousRotation 616 public Quaternion PreviousRotation
@@ -581,11 +635,21 @@ namespace OpenSim.Region.Framework.Scenes
581 635
582 private uint m_parentID; 636 private uint m_parentID;
583 637
638
639 private UUID m_linkedPrim;
640
584 public uint ParentID 641 public uint ParentID
585 { 642 {
586 get { return m_parentID; } 643 get { return m_parentID; }
587 set { m_parentID = value; } 644 set { m_parentID = value; }
588 } 645 }
646
647 public UUID LinkedPrim
648 {
649 get { return m_linkedPrim; }
650 set { m_linkedPrim = value; }
651 }
652
589 public float Health 653 public float Health
590 { 654 {
591 get { return m_health; } 655 get { return m_health; }
@@ -707,7 +771,7 @@ namespace OpenSim.Region.Framework.Scenes
707 CreateSceneViewer(); 771 CreateSceneViewer();
708 m_animator = new ScenePresenceAnimator(this); 772 m_animator = new ScenePresenceAnimator(this);
709 } 773 }
710 774
711 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this() 775 private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
712 { 776 {
713 m_DrawDistance = world.DefaultDrawDistance; 777 m_DrawDistance = world.DefaultDrawDistance;
@@ -722,6 +786,7 @@ namespace OpenSim.Region.Framework.Scenes
722 m_localId = m_scene.AllocateLocalId(); 786 m_localId = m_scene.AllocateLocalId();
723 787
724 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 788 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
789 m_userFlags = account.UserFlags;
725 790
726 if (account != null) 791 if (account != null)
727 m_userLevel = account.UserLevel; 792 m_userLevel = account.UserLevel;
@@ -740,10 +805,7 @@ namespace OpenSim.Region.Framework.Scenes
740 m_reprioritization_timer.AutoReset = false; 805 m_reprioritization_timer.AutoReset = false;
741 806
742 AdjustKnownSeeds(); 807 AdjustKnownSeeds();
743
744 // TODO: I think, this won't send anything, as we are still a child here...
745 Animator.TrySetMovementAnimation("STAND"); 808 Animator.TrySetMovementAnimation("STAND");
746
747 // we created a new ScenePresence (a new child agent) in a fresh region. 809 // we created a new ScenePresence (a new child agent) in a fresh region.
748 // Request info about all the (root) agents in this region 810 // Request info about all the (root) agents in this region
749 // Note: This won't send data *to* other clients in that region (children don't send) 811 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -794,25 +856,47 @@ namespace OpenSim.Region.Framework.Scenes
794 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 856 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
795 Dir_Vectors[4] = Vector3.UnitZ; //UP 857 Dir_Vectors[4] = Vector3.UnitZ; //UP
796 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 858 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
797 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 859 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
798 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 860 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
799 Dir_Vectors[7] = -Vector3.UnitX; //BACK 861 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
862 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
863 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
800 } 864 }
801 865
802 private Vector3[] GetWalkDirectionVectors() 866 private Vector3[] GetWalkDirectionVectors()
803 { 867 {
804 Vector3[] vector = new Vector3[9]; 868 Vector3[] vector = new Vector3[11];
805 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 869 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
806 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 870 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
807 vector[2] = Vector3.UnitY; //LEFT 871 vector[2] = Vector3.UnitY; //LEFT
808 vector[3] = -Vector3.UnitY; //RIGHT 872 vector[3] = -Vector3.UnitY; //RIGHT
809 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 873 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
810 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 874 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
811 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 875 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
812 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 876 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
813 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 877 vector[8] = Vector3.UnitY; //LEFT_NUDGE
878 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
879 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
814 return vector; 880 return vector;
815 } 881 }
882
883 private bool[] GetDirectionIsNudge()
884 {
885 bool[] isNudge = new bool[11];
886 isNudge[0] = false; //FORWARD
887 isNudge[1] = false; //BACK
888 isNudge[2] = false; //LEFT
889 isNudge[3] = false; //RIGHT
890 isNudge[4] = false; //UP
891 isNudge[5] = false; //DOWN
892 isNudge[6] = true; //FORWARD_NUDGE
893 isNudge[7] = true; //BACK_NUDGE
894 isNudge[8] = true; //LEFT_NUDGE
895 isNudge[9] = true; //RIGHT_NUDGE
896 isNudge[10] = true; //DOWN_Nudge
897 return isNudge;
898 }
899
816 900
817 #endregion 901 #endregion
818 902
@@ -877,6 +961,62 @@ namespace OpenSim.Region.Framework.Scenes
877 pos.Y = crossedBorder.BorderLine.Z - 1; 961 pos.Y = crossedBorder.BorderLine.Z - 1;
878 } 962 }
879 963
964 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
965 if (land != null)
966 {
967 // If we come in via login, landmark or map, we want to
968 // honor landing points. If we come in via Lure, we want
969 // to ignore them.
970 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
971 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ||
972 (m_teleportFlags & TeleportFlags.ViaLocation) != 0)
973 {
974 // Don't restrict gods, estate managers, or land owners to
975 // the TP point. This behaviour mimics agni.
976 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
977 land.LandData.UserLocation != Vector3.Zero &&
978 GodLevel < 200 &&
979 ((land.LandData.OwnerID != m_uuid &&
980 (!m_scene.Permissions.IsGod(m_uuid)) &&
981 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0))
982 {
983 pos = land.LandData.UserLocation;
984 }
985 }
986
987 land.SendLandUpdateToClient(ControllingClient);
988 }
989
990 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
991 {
992 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
993
994 if (pos.X < 0)
995 {
996 emergencyPos.X = (int)Constants.RegionSize + pos.X;
997 if (!(pos.Y < 0))
998 emergencyPos.Y = pos.Y;
999 if (!(pos.Z < 0))
1000 emergencyPos.Z = pos.Z;
1001 }
1002 if (pos.Y < 0)
1003 {
1004 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
1005 if (!(pos.X < 0))
1006 emergencyPos.X = pos.X;
1007 if (!(pos.Z < 0))
1008 emergencyPos.Z = pos.Z;
1009 }
1010 if (pos.Z < 0)
1011 {
1012 emergencyPos.Z = 128;
1013 if (!(pos.Y < 0))
1014 emergencyPos.Y = pos.Y;
1015 if (!(pos.X < 0))
1016 emergencyPos.X = pos.X;
1017 }
1018 }
1019
880 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1020 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
881 { 1021 {
882 m_log.WarnFormat( 1022 m_log.WarnFormat(
@@ -1022,16 +1162,21 @@ namespace OpenSim.Region.Framework.Scenes
1022 /// <summary> 1162 /// <summary>
1023 /// Removes physics plugin scene representation of this agent if it exists. 1163 /// Removes physics plugin scene representation of this agent if it exists.
1024 /// </summary> 1164 /// </summary>
1025 private void RemoveFromPhysicalScene() 1165 public void RemoveFromPhysicalScene()
1026 { 1166 {
1027 if (PhysicsActor != null) 1167 if (PhysicsActor != null)
1028 { 1168 {
1029 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1169 try
1030 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1170 {
1031 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1171 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1032 m_physicsActor.UnSubscribeEvents(); 1172 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
1033 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1173 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1034 PhysicsActor = null; 1174 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1175 m_physicsActor.UnSubscribeEvents();
1176 PhysicsActor = null;
1177 }
1178 catch
1179 { }
1035 } 1180 }
1036 } 1181 }
1037 1182
@@ -1042,11 +1187,13 @@ namespace OpenSim.Region.Framework.Scenes
1042 public void Teleport(Vector3 pos) 1187 public void Teleport(Vector3 pos)
1043 { 1188 {
1044 bool isFlying = false; 1189 bool isFlying = false;
1190
1045 if (m_physicsActor != null) 1191 if (m_physicsActor != null)
1046 isFlying = m_physicsActor.Flying; 1192 isFlying = m_physicsActor.Flying;
1047 1193
1048 RemoveFromPhysicalScene(); 1194 RemoveFromPhysicalScene();
1049 Velocity = Vector3.Zero; 1195 Velocity = Vector3.Zero;
1196 CheckLandingPoint(ref pos);
1050 AbsolutePosition = pos; 1197 AbsolutePosition = pos;
1051 AddToPhysicalScene(isFlying); 1198 AddToPhysicalScene(isFlying);
1052 if (m_appearance != null) 1199 if (m_appearance != null)
@@ -1056,6 +1203,7 @@ namespace OpenSim.Region.Framework.Scenes
1056 } 1203 }
1057 1204
1058 SendTerseUpdateToAllClients(); 1205 SendTerseUpdateToAllClients();
1206
1059 } 1207 }
1060 1208
1061 public void TeleportWithMomentum(Vector3 pos) 1209 public void TeleportWithMomentum(Vector3 pos)
@@ -1065,6 +1213,7 @@ namespace OpenSim.Region.Framework.Scenes
1065 isFlying = m_physicsActor.Flying; 1213 isFlying = m_physicsActor.Flying;
1066 1214
1067 RemoveFromPhysicalScene(); 1215 RemoveFromPhysicalScene();
1216 CheckLandingPoint(ref pos);
1068 AbsolutePosition = pos; 1217 AbsolutePosition = pos;
1069 AddToPhysicalScene(isFlying); 1218 AddToPhysicalScene(isFlying);
1070 if (m_appearance != null) 1219 if (m_appearance != null)
@@ -1275,6 +1424,7 @@ namespace OpenSim.Region.Framework.Scenes
1275 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1424 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1276 1425
1277 m_pos = m_LastFinitePos; 1426 m_pos = m_LastFinitePos;
1427
1278 if (!m_pos.IsFinite()) 1428 if (!m_pos.IsFinite())
1279 { 1429 {
1280 m_pos.X = 127f; 1430 m_pos.X = 127f;
@@ -1345,7 +1495,6 @@ namespace OpenSim.Region.Framework.Scenes
1345 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1495 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1346 } 1496 }
1347 } 1497 }
1348
1349 lock (scriptedcontrols) 1498 lock (scriptedcontrols)
1350 { 1499 {
1351 if (scriptedcontrols.Count > 0) 1500 if (scriptedcontrols.Count > 0)
@@ -1360,6 +1509,9 @@ namespace OpenSim.Region.Framework.Scenes
1360 1509
1361 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1510 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1362 { 1511 {
1512 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1513 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1514
1363 // TODO: This doesn't prevent the user from walking yet. 1515 // TODO: This doesn't prevent the user from walking yet.
1364 // Setting parent ID would fix this, if we knew what value 1516 // Setting parent ID would fix this, if we knew what value
1365 // to use. Or we could add a m_isSitting variable. 1517 // to use. Or we could add a m_isSitting variable.
@@ -1408,12 +1560,20 @@ namespace OpenSim.Region.Framework.Scenes
1408 if (actor.Flying != oldflying) 1560 if (actor.Flying != oldflying)
1409 update_movementflag = true; 1561 update_movementflag = true;
1410 1562
1563 if (m_animator.m_jumping) // add for jumping
1564 update_movementflag = true;
1565
1411 if (q != m_bodyRot) 1566 if (q != m_bodyRot)
1412 { 1567 {
1413 m_bodyRot = q; 1568 m_bodyRot = q;
1414 update_rotation = true; 1569 update_rotation = true;
1415 } 1570 }
1416 1571
1572 //guilty until proven innocent..
1573 bool Nudging = true;
1574 //Basically, if there is at least one non-nudge control then we don't need
1575 //to worry about stopping the avatar
1576
1417 if (m_parentID == 0) 1577 if (m_parentID == 0)
1418 { 1578 {
1419 bool bAllowUpdateMoveToPosition = false; 1579 bool bAllowUpdateMoveToPosition = false;
@@ -1428,9 +1588,12 @@ namespace OpenSim.Region.Framework.Scenes
1428 else 1588 else
1429 dirVectors = Dir_Vectors; 1589 dirVectors = Dir_Vectors;
1430 1590
1431 // The fact that m_movementflag is a byte needs to be fixed 1591 bool[] isNudge = GetDirectionIsNudge();
1432 // it really should be a uint 1592
1433 uint nudgehack = 250; 1593
1594
1595
1596
1434 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1597 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1435 { 1598 {
1436 if (((uint)flags & (uint)DCF) != 0) 1599 if (((uint)flags & (uint)DCF) != 0)
@@ -1440,40 +1603,28 @@ namespace OpenSim.Region.Framework.Scenes
1440 try 1603 try
1441 { 1604 {
1442 agent_control_v3 += dirVectors[i]; 1605 agent_control_v3 += dirVectors[i];
1443 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1606 if (isNudge[i] == false)
1607 {
1608 Nudging = false;
1609 }
1444 } 1610 }
1445 catch (IndexOutOfRangeException) 1611 catch (IndexOutOfRangeException)
1446 { 1612 {
1447 // Why did I get this? 1613 // Why did I get this?
1448 } 1614 }
1449 1615
1450 if ((m_movementflag & (byte)(uint)DCF) == 0) 1616 if ((m_movementflag & (uint)DCF) == 0)
1451 { 1617 {
1452 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1453 {
1454 m_movementflag |= (byte)nudgehack;
1455 }
1456 m_movementflag += (byte)(uint)DCF; 1618 m_movementflag += (byte)(uint)DCF;
1457 update_movementflag = true; 1619 update_movementflag = true;
1458 } 1620 }
1459 } 1621 }
1460 else 1622 else
1461 { 1623 {
1462 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1624 if ((m_movementflag & (uint)DCF) != 0)
1463 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1464 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1465 ) // This or is for Nudge forward
1466 { 1625 {
1467 m_movementflag -= ((byte)(uint)DCF); 1626 m_movementflag -= (byte)(uint)DCF;
1468
1469 update_movementflag = true; 1627 update_movementflag = true;
1470 /*
1471 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1472 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1473 {
1474 m_log.Debug("Removed Hack flag");
1475 }
1476 */
1477 } 1628 }
1478 else 1629 else
1479 { 1630 {
@@ -1482,7 +1633,6 @@ namespace OpenSim.Region.Framework.Scenes
1482 } 1633 }
1483 i++; 1634 i++;
1484 } 1635 }
1485
1486 //Paupaw:Do Proper PID for Autopilot here 1636 //Paupaw:Do Proper PID for Autopilot here
1487 if (bResetMoveToPosition) 1637 if (bResetMoveToPosition)
1488 { 1638 {
@@ -1494,8 +1644,41 @@ namespace OpenSim.Region.Framework.Scenes
1494 1644
1495 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving)) 1645 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
1496 { 1646 {
1647/*
1648 bool twoD = false;
1649 bool there = false;
1650 if (Animator != null)
1651 {
1652 switch (Animator.CurrentMovementAnimation)
1653 {
1654 case "STAND":
1655 case "WALK":
1656 case "RUN":
1657 case "CROUCH":
1658 case "CROUCHWALK":
1659 {
1660 twoD = true;
1661 }
1662 break;
1663 }
1664 }
1665
1666 if (twoD)
1667 {
1668*/
1669 Vector3 abspos = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, 0.0f);
1670 Vector3 tgt = new Vector3(m_moveToPositionTarget.X, m_moveToPositionTarget.Y, 0.0f);
1671/* if (Util.GetDistanceTo(abspos, tgt) <= 0.5f) there = true;
1672 }
1673 else
1674 {
1675 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) there = true;
1676 }
1677*/
1497 //Check the error term of the current position in relation to the target position 1678 //Check the error term of the current position in relation to the target position
1498 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) 1679// if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
1680// if (there)
1681 if (Util.GetDistanceTo(abspos, tgt) <= 0.5f)
1499 { 1682 {
1500 // we are close enough to the target 1683 // we are close enough to the target
1501 m_moveToPositionTarget = Vector3.Zero; 1684 m_moveToPositionTarget = Vector3.Zero;
@@ -1512,11 +1695,15 @@ namespace OpenSim.Region.Framework.Scenes
1512 // unknown forces are acting on the avatar and we need to adaptively respond 1695 // unknown forces are acting on the avatar and we need to adaptively respond
1513 // to such forces, but the following simple approach seems to works fine. 1696 // to such forces, but the following simple approach seems to works fine.
1514 Vector3 LocalVectorToTarget3D = 1697 Vector3 LocalVectorToTarget3D =
1515 (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords 1698// (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
1699 (tgt - abspos)
1516 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords 1700 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
1517 // Ignore z component of vector 1701 // Ignore z component of vector
1518 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f); 1702 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1519 LocalVectorToTarget2D.Normalize(); 1703 LocalVectorToTarget2D.Normalize();
1704
1705 //We're not nudging
1706 Nudging = false;
1520 agent_control_v3 += LocalVectorToTarget2D; 1707 agent_control_v3 += LocalVectorToTarget2D;
1521 1708
1522 // update avatar movement flags. the avatar coordinate system is as follows: 1709 // update avatar movement flags. the avatar coordinate system is as follows:
@@ -1607,13 +1794,13 @@ namespace OpenSim.Region.Framework.Scenes
1607 // m_log.DebugFormat( 1794 // m_log.DebugFormat(
1608 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3); 1795 // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
1609 1796
1610 AddNewMovement(agent_control_v3, q); 1797 AddNewMovement(agent_control_v3, q, Nudging);
1611 1798
1612 1799
1613 } 1800 }
1614 } 1801 }
1615 1802
1616 if (update_movementflag && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) == 0) && (m_parentID == 0) && !SitGround) 1803 if (update_movementflag && !SitGround)
1617 Animator.UpdateMovementAnimations(); 1804 Animator.UpdateMovementAnimations();
1618 1805
1619 m_scene.EventManager.TriggerOnClientMovement(this); 1806 m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1628,7 +1815,6 @@ namespace OpenSim.Region.Framework.Scenes
1628 m_sitAtAutoTarget = false; 1815 m_sitAtAutoTarget = false;
1629 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default; 1816 PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
1630 //proxy.PCode = (byte)PCode.ParticleSystem; 1817 //proxy.PCode = (byte)PCode.ParticleSystem;
1631
1632 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy); 1818 proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
1633 proxyObjectGroup.AttachToScene(m_scene); 1819 proxyObjectGroup.AttachToScene(m_scene);
1634 1820
@@ -1647,8 +1833,15 @@ namespace OpenSim.Region.Framework.Scenes
1647// } 1833// }
1648 } 1834 }
1649 1835
1836 public void StopMoveToPosition()
1837 {
1838 m_moveToPositionTarget = Vector3.Zero;
1839 m_moveToPositionInProgress = false;
1840 }
1841
1650 public void DoMoveToPosition(Object sender, string method, List<String> args) 1842 public void DoMoveToPosition(Object sender, string method, List<String> args)
1651 { 1843 {
1844//Console.WriteLine("SP:DoMoveToPosition");
1652 try 1845 try
1653 { 1846 {
1654 float locx = 0f; 1847 float locx = 0f;
@@ -1670,7 +1863,7 @@ namespace OpenSim.Region.Framework.Scenes
1670 } 1863 }
1671 m_moveToPositionInProgress = true; 1864 m_moveToPositionInProgress = true;
1672 m_moveToPositionTarget = new Vector3(locx, locy, locz); 1865 m_moveToPositionTarget = new Vector3(locx, locy, locz);
1673 } 1866 }
1674 catch (Exception ex) 1867 catch (Exception ex)
1675 { 1868 {
1676 //Why did I get this error? 1869 //Why did I get this error?
@@ -1692,7 +1885,7 @@ namespace OpenSim.Region.Framework.Scenes
1692 Velocity = Vector3.Zero; 1885 Velocity = Vector3.Zero;
1693 SendAvatarDataToAllAgents(); 1886 SendAvatarDataToAllAgents();
1694 1887
1695 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 1888 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1696 } 1889 }
1697 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 1890 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1698 m_requestedSitTargetUUID = UUID.Zero; 1891 m_requestedSitTargetUUID = UUID.Zero;
@@ -1729,25 +1922,22 @@ namespace OpenSim.Region.Framework.Scenes
1729 1922
1730 if (m_parentID != 0) 1923 if (m_parentID != 0)
1731 { 1924 {
1732 m_log.Debug("StandupCode Executed"); 1925 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1733 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1734 if (part != null) 1926 if (part != null)
1735 { 1927 {
1928 part.TaskInventory.LockItemsForRead(true);
1736 TaskInventoryDictionary taskIDict = part.TaskInventory; 1929 TaskInventoryDictionary taskIDict = part.TaskInventory;
1737 if (taskIDict != null) 1930 if (taskIDict != null)
1738 { 1931 {
1739 lock (taskIDict) 1932 foreach (UUID taskID in taskIDict.Keys)
1740 { 1933 {
1741 foreach (UUID taskID in taskIDict.Keys) 1934 UnRegisterControlEventsToScript(LocalId, taskID);
1742 { 1935 taskIDict[taskID].PermsMask &= ~(
1743 UnRegisterControlEventsToScript(LocalId, taskID); 1936 2048 | //PERMISSION_CONTROL_CAMERA
1744 taskIDict[taskID].PermsMask &= ~( 1937 4); // PERMISSION_TAKE_CONTROLS
1745 2048 | //PERMISSION_CONTROL_CAMERA
1746 4); // PERMISSION_TAKE_CONTROLS
1747 }
1748 } 1938 }
1749
1750 } 1939 }
1940 part.TaskInventory.LockItemsForRead(false);
1751 // Reset sit target. 1941 // Reset sit target.
1752 if (part.GetAvatarOnSitTarget() == UUID) 1942 if (part.GetAvatarOnSitTarget() == UUID)
1753 part.SitTargetAvatar = UUID.Zero; 1943 part.SitTargetAvatar = UUID.Zero;
@@ -1756,16 +1946,55 @@ namespace OpenSim.Region.Framework.Scenes
1756 m_parentPosition = part.GetWorldPosition(); 1946 m_parentPosition = part.GetWorldPosition();
1757 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1947 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1758 } 1948 }
1949 // part.GetWorldRotation() is the rotation of the object being sat on
1950 // Rotation is the sittiing Av's rotation
1951
1952 Quaternion partRot;
1953// if (part.LinkNum == 1)
1954// { // Root prim of linkset
1955// partRot = part.ParentGroup.RootPart.RotationOffset;
1956// }
1957// else
1958// { // single or child prim
1959
1960// }
1961 if (part == null) //CW: Part may be gone. llDie() for example.
1962 {
1963 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1964 }
1965 else
1966 {
1967 partRot = part.GetWorldRotation();
1968 }
1759 1969
1970 Quaternion partIRot = Quaternion.Inverse(partRot);
1971
1972 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
1973 Vector3 avStandUp = new Vector3(0.3f, 0f, 0f) * avatarRot; // 0.3M infront of av
1974
1975
1760 if (m_physicsActor == null) 1976 if (m_physicsActor == null)
1761 { 1977 {
1762 AddToPhysicalScene(false); 1978 AddToPhysicalScene(false);
1763 } 1979 }
1764 1980 //CW: If the part isn't null then we can set the current position
1765 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 1981 if (part != null)
1766 m_parentPosition = Vector3.Zero; 1982 {
1767 1983 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1768 m_parentID = 0; 1984 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
1985 part.IsOccupied = false;
1986 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
1987 }
1988 else
1989 {
1990 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
1991 AbsolutePosition = m_lastWorldPosition;
1992 }
1993
1994 m_parentPosition = Vector3.Zero;
1995 m_parentID = 0;
1996 m_linkedPrim = UUID.Zero;
1997 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1769 SendAvatarDataToAllAgents(); 1998 SendAvatarDataToAllAgents();
1770 m_requestedSitTargetID = 0; 1999 m_requestedSitTargetID = 0;
1771 if (m_physicsActor != null && m_appearance != null) 2000 if (m_physicsActor != null && m_appearance != null)
@@ -1774,7 +2003,6 @@ namespace OpenSim.Region.Framework.Scenes
1774 SetHeight(m_appearance.AvatarHeight); 2003 SetHeight(m_appearance.AvatarHeight);
1775 } 2004 }
1776 } 2005 }
1777
1778 Animator.TrySetMovementAnimation("STAND"); 2006 Animator.TrySetMovementAnimation("STAND");
1779 } 2007 }
1780 2008
@@ -1805,13 +2033,9 @@ namespace OpenSim.Region.Framework.Scenes
1805 Vector3 avSitOffSet = part.SitTargetPosition; 2033 Vector3 avSitOffSet = part.SitTargetPosition;
1806 Quaternion avSitOrientation = part.SitTargetOrientation; 2034 Quaternion avSitOrientation = part.SitTargetOrientation;
1807 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2035 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1808 2036 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1809 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2037 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1810 bool SitTargetisSet = 2038 if (SitTargetisSet && !SitTargetOccupied)
1811 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1812 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1813
1814 if (SitTargetisSet && SitTargetUnOccupied)
1815 { 2039 {
1816 //switch the target to this prim 2040 //switch the target to this prim
1817 return part; 2041 return part;
@@ -1825,85 +2049,168 @@ namespace OpenSim.Region.Framework.Scenes
1825 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 2049 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1826 { 2050 {
1827 bool autopilot = true; 2051 bool autopilot = true;
2052 Vector3 autopilotTarget = new Vector3();
2053 Quaternion sitOrientation = Quaternion.Identity;
1828 Vector3 pos = new Vector3(); 2054 Vector3 pos = new Vector3();
1829 Quaternion sitOrientation = pSitOrientation;
1830 Vector3 cameraEyeOffset = Vector3.Zero; 2055 Vector3 cameraEyeOffset = Vector3.Zero;
1831 Vector3 cameraAtOffset = Vector3.Zero; 2056 Vector3 cameraAtOffset = Vector3.Zero;
1832 bool forceMouselook = false; 2057 bool forceMouselook = false;
1833 2058
1834 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 2059 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1835 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 2060 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1836 if (part != null) 2061 if (part == null) return;
1837 { 2062
1838 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 2063 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
1839 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 2064 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
1840 2065
1841 // Is a sit target available? 2066 // part is the prim to sit on
1842 Vector3 avSitOffSet = part.SitTargetPosition; 2067 // offset is the world-ref vector distance from that prim center to the click-spot
1843 Quaternion avSitOrientation = part.SitTargetOrientation; 2068 // UUID is the UUID of the Avatar doing the clicking
1844 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2069
1845 2070 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
1846 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2071
1847 bool SitTargetisSet = 2072 // Is a sit target available?
1848 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && 2073 Vector3 avSitOffSet = part.SitTargetPosition;
1849 ( 2074 Quaternion avSitOrientation = part.SitTargetOrientation;
1850 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion 2075
1851 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point 2076 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1852 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion 2077 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
1853 ) 2078 Quaternion partRot;
1854 )); 2079// if (part.LinkNum == 1)
1855 2080// { // Root prim of linkset
1856 if (SitTargetisSet && SitTargetUnOccupied) 2081// partRot = part.ParentGroup.RootPart.RotationOffset;
1857 { 2082// }
1858 part.SitTargetAvatar = UUID; 2083// else
1859 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); 2084// { // single or child prim
1860 sitOrientation = avSitOrientation; 2085 partRot = part.GetWorldRotation();
1861 autopilot = false; 2086// }
1862 } 2087 Quaternion partIRot = Quaternion.Inverse(partRot);
1863 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 2088//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
1864 2089 // Sit analysis rewritten by KF 091125
1865 pos = part.AbsolutePosition + offset; 2090 if (SitTargetisSet) // scipted sit
1866 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1) 2091 {
1867 //{ 2092 if (!part.IsOccupied)
1868 // offset = pos; 2093 {
1869 //autopilot = false; 2094//Console.WriteLine("Scripted, unoccupied");
1870 //} 2095 part.SitTargetAvatar = UUID; // set that Av will be on it
1871 if (m_physicsActor != null) 2096 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1872 { 2097
1873 // If we're not using the client autopilot, we're immediately warping the avatar to the location 2098 Quaternion nrot = avSitOrientation;
1874 // We can remove the physicsActor until they stand up. 2099 if (!part.IsRoot)
1875 m_sitAvatarHeight = m_physicsActor.Size.Z;
1876
1877 if (autopilot)
1878 { 2100 {
1879 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 2101 nrot = part.RotationOffset * avSitOrientation;
1880 {
1881 autopilot = false;
1882
1883 RemoveFromPhysicalScene();
1884 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1885 }
1886 } 2102 }
1887 else 2103 sitOrientation = nrot; // Change rotatione to the scripted one
2104 OffsetRotation = nrot;
2105 autopilot = false; // Jump direct to scripted llSitPos()
2106 }
2107 else
2108 {
2109//Console.WriteLine("Scripted, occupied");
2110 return;
2111 }
2112 }
2113 else // Not Scripted
2114 {
2115 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
2116 {
2117 // large prim & offset, ignore if other Avs sitting
2118// offset.Z -= 0.05f;
2119 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
2120 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
2121
2122//Console.WriteLine(" offset ={0}", offset);
2123//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
2124//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
2125
2126 }
2127 else // small offset
2128 {
2129//Console.WriteLine("Small offset");
2130 if (!part.IsOccupied)
2131 {
2132 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2133 autopilotTarget = part.AbsolutePosition;
2134//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2135 }
2136 else return; // occupied small
2137 } // end large/small
2138 } // end Scripted/not
2139
2140 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2141
2142 cameraAtOffset = part.GetCameraAtOffset();
2143 cameraEyeOffset = part.GetCameraEyeOffset();
2144 forceMouselook = part.GetForceMouselook();
2145 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2146 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2147
2148 if (m_physicsActor != null)
2149 {
2150 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2151 // We can remove the physicsActor until they stand up.
2152 m_sitAvatarHeight = m_physicsActor.Size.Z;
2153 if (autopilot)
2154 { // its not a scripted sit
2155// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2156 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1888 { 2157 {
2158 autopilot = false; // close enough
2159 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2160 Not using the part's position because returning the AV to the last known standing
2161 position is likely to be more friendly, isn't it? */
1889 RemoveFromPhysicalScene(); 2162 RemoveFromPhysicalScene();
1890 } 2163 Velocity = Vector3.Zero;
2164 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2165 } // else the autopilot will get us close
2166 }
2167 else
2168 { // its a scripted sit
2169 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2170 I *am* using the part's position this time because we have no real idea how far away
2171 the avatar is from the sit target. */
2172 RemoveFromPhysicalScene();
2173 Velocity = Vector3.Zero;
1891 } 2174 }
1892
1893 cameraAtOffset = part.GetCameraAtOffset();
1894 cameraEyeOffset = part.GetCameraEyeOffset();
1895 forceMouselook = part.GetForceMouselook();
1896 } 2175 }
1897 2176 else return; // physactor is null!
1898 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2177
1899 m_requestedSitTargetUUID = targetID; 2178 Vector3 offsetr; // = offset * partIRot;
2179 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2180 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2181 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2182 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2183 //offsetr = offset * partIRot;
2184//
2185 // }
2186 // else
2187 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2188 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2189 // (offset * partRot);
2190 // }
2191
2192//Console.WriteLine(" ");
2193//Console.WriteLine("link number ={0}", part.LinkNum);
2194//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2195//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2196//Console.WriteLine("Click offst ={0}", offset);
2197//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2198//Console.WriteLine("offsetr ={0}", offsetr);
2199//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2200//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2201
2202 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2203 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2204
2205 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1900 // This calls HandleAgentSit twice, once from here, and the client calls 2206 // This calls HandleAgentSit twice, once from here, and the client calls
1901 // HandleAgentSit itself after it gets to the location 2207 // HandleAgentSit itself after it gets to the location
1902 // It doesn't get to the location until we've moved them there though 2208 // It doesn't get to the location until we've moved them there though
1903 // which happens in HandleAgentSit :P 2209 // which happens in HandleAgentSit :P
1904 m_autopilotMoving = autopilot; 2210 m_autopilotMoving = autopilot;
1905 m_autoPilotTarget = pos; 2211 m_autoPilotTarget = autopilotTarget;
1906 m_sitAtAutoTarget = autopilot; 2212 m_sitAtAutoTarget = autopilot;
2213 m_initialSitTarget = autopilotTarget;
1907 if (!autopilot) 2214 if (!autopilot)
1908 HandleAgentSit(remoteClient, UUID); 2215 HandleAgentSit(remoteClient, UUID);
1909 } 2216 }
@@ -2197,47 +2504,130 @@ namespace OpenSim.Region.Framework.Scenes
2197 { 2504 {
2198 if (part != null) 2505 if (part != null)
2199 { 2506 {
2507//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2200 if (part.GetAvatarOnSitTarget() == UUID) 2508 if (part.GetAvatarOnSitTarget() == UUID)
2201 { 2509 {
2510//Console.WriteLine("Scripted Sit");
2511 // Scripted sit
2202 Vector3 sitTargetPos = part.SitTargetPosition; 2512 Vector3 sitTargetPos = part.SitTargetPosition;
2203 Quaternion sitTargetOrient = part.SitTargetOrientation; 2513 Quaternion sitTargetOrient = part.SitTargetOrientation;
2204
2205 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2206 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2207
2208 //Quaternion result = (sitTargetOrient * vq) * nq;
2209
2210 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2514 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2211 m_pos += SIT_TARGET_ADJUSTMENT; 2515 m_pos += SIT_TARGET_ADJUSTMENT;
2516 if (!part.IsRoot)
2517 {
2518 m_pos *= part.RotationOffset;
2519 }
2212 m_bodyRot = sitTargetOrient; 2520 m_bodyRot = sitTargetOrient;
2213 //Rotation = sitTargetOrient;
2214 m_parentPosition = part.AbsolutePosition; 2521 m_parentPosition = part.AbsolutePosition;
2215 2522 part.IsOccupied = true;
2216 //SendTerseUpdateToAllClients(); 2523 part.ParentGroup.AddAvatar(agentID);
2217 } 2524 }
2218 else 2525 else
2219 { 2526 {
2220 m_pos -= part.AbsolutePosition; 2527 // if m_avUnscriptedSitPos is zero then Av sits above center
2528 // Else Av sits at m_avUnscriptedSitPos
2529
2530 // Non-scripted sit by Kitto Flora 21Nov09
2531 // Calculate angle of line from prim to Av
2532 Quaternion partIRot;
2533// if (part.LinkNum == 1)
2534// { // Root prim of linkset
2535// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2536// }
2537// else
2538// { // single or child prim
2539 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2540// }
2541 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2542 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2543 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2544 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2545 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2546 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2547 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2548 // Av sits at world euler <0,0, z>, translated by part rotation
2549 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2550
2221 m_parentPosition = part.AbsolutePosition; 2551 m_parentPosition = part.AbsolutePosition;
2222 } 2552 part.IsOccupied = true;
2553 part.ParentGroup.AddAvatar(agentID);
2554 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2555 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2556 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2557 m_avUnscriptedSitPos; // adds click offset, if any
2558 //Set up raytrace to find top surface of prim
2559 Vector3 size = part.Scale;
2560 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2561 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2562 Vector3 down = new Vector3(0f, 0f, -1f);
2563//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2564 m_scene.PhysicsScene.RaycastWorld(
2565 start, // Vector3 position,
2566 down, // Vector3 direction,
2567 mag, // float length,
2568 SitAltitudeCallback); // retMethod
2569 } // end scripted/not
2223 } 2570 }
2224 else 2571 else // no Av
2225 { 2572 {
2226 return; 2573 return;
2227 } 2574 }
2228 } 2575 }
2229 m_parentID = m_requestedSitTargetID;
2230 2576
2577 //We want our offsets to reference the root prim, not the child we may have sat on
2578 if (!part.IsRoot)
2579 {
2580 m_parentID = part.ParentGroup.RootPart.LocalId;
2581 m_pos += part.OffsetPosition;
2582 }
2583 else
2584 {
2585 m_parentID = m_requestedSitTargetID;
2586 }
2587
2588 m_linkedPrim = part.UUID;
2589 if (part.GetAvatarOnSitTarget() != UUID)
2590 {
2591 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2592 }
2231 Velocity = Vector3.Zero; 2593 Velocity = Vector3.Zero;
2232 RemoveFromPhysicalScene(); 2594 RemoveFromPhysicalScene();
2233
2234 Animator.TrySetMovementAnimation(sitAnimation); 2595 Animator.TrySetMovementAnimation(sitAnimation);
2235 SendAvatarDataToAllAgents(); 2596 SendAvatarDataToAllAgents();
2236 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2237 // So we're also sending a terse update (which has avatar rotation)
2238 // [Update] We do now.
2239 //SendTerseUpdateToAllClients(); 2597 //SendTerseUpdateToAllClients();
2240 } 2598 }
2599
2600 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2601 {
2602 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2603 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2604 if(hitYN)
2605 {
2606 // m_pos = Av offset from prim center to make look like on center
2607 // m_parentPosition = Actual center pos of prim
2608 // collisionPoint = spot on prim where we want to sit
2609 // collisionPoint.Z = global sit surface height
2610 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2611 Quaternion partIRot;
2612// if (part.LinkNum == 1)
2613/// { // Root prim of linkset
2614// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2615// }
2616// else
2617// { // single or child prim
2618 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2619// }
2620 if (m_initialSitTarget != null)
2621 {
2622 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2623 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2624 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2625 m_pos += offset;
2626 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2627 }
2628
2629 }
2630 } // End SitAltitudeCallback KF.
2241 2631
2242 /// <summary> 2632 /// <summary>
2243 /// Event handler for the 'Always run' setting on the client 2633 /// Event handler for the 'Always run' setting on the client
@@ -2267,12 +2657,13 @@ namespace OpenSim.Region.Framework.Scenes
2267 /// </summary> 2657 /// </summary>
2268 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2658 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2269 /// <param name="rotation">The direction in which this avatar should now face. 2659 /// <param name="rotation">The direction in which this avatar should now face.
2270 public void AddNewMovement(Vector3 vec, Quaternion rotation) 2660 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2271 { 2661 {
2272 if (m_isChildAgent) 2662 if (m_isChildAgent)
2273 { 2663 {
2274 // WHAT??? 2664 // WHAT???
2275 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!"); 2665 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent");
2666
2276 return; 2667 return;
2277 } 2668 }
2278 2669
@@ -2281,15 +2672,26 @@ namespace OpenSim.Region.Framework.Scenes
2281 Rotation = rotation; 2672 Rotation = rotation;
2282 Vector3 direc = vec * rotation; 2673 Vector3 direc = vec * rotation;
2283 direc.Normalize(); 2674 direc.Normalize();
2675 PhysicsActor actor = m_physicsActor;
2676
2677 if (actor.Flying != m_flyingOld) // add for fly velocity control
2678 {
2679 m_flyingOld = actor.Flying; // add for fly velocity control
2680 if (!actor.Flying) m_wasFlying = true; // add for fly velocity control
2681 }
2682
2683 if (m_physicsActor.IsColliding == true) m_wasFlying = false; // add for fly velocity control
2684
2685 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2284 2686
2285 direc *= 0.03f * 128f * m_speedModifier; 2687 direc *= 0.03f * 128f * m_speedModifier;
2286 2688
2287 PhysicsActor actor = m_physicsActor;
2288 if (actor != null) 2689 if (actor != null)
2289 { 2690 {
2290 if (actor.Flying) 2691 if (actor.Flying)
2291 { 2692 {
2292 direc *= 4.0f; 2693// rm speed mod direc *= 4.0f;
2694 direc *= 5.2f; // for speed mod
2293 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2695 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2294 //bool colliding = (m_physicsActor.IsColliding==true); 2696 //bool colliding = (m_physicsActor.IsColliding==true);
2295 //if (controlland) 2697 //if (controlland)
@@ -2302,22 +2704,34 @@ namespace OpenSim.Region.Framework.Scenes
2302 // m_log.Info("[AGENT]: Stop FLying"); 2704 // m_log.Info("[AGENT]: Stop FLying");
2303 //} 2705 //}
2304 } 2706 }
2707 if (Animator.m_falling && m_wasFlying) // if falling from flying, disable motion add
2708 {
2709 direc *= 0.0f;
2710 }
2711 /* This jumping section removed to SPA
2305 else if (!actor.Flying && actor.IsColliding) 2712 else if (!actor.Flying && actor.IsColliding)
2306 { 2713 {
2307 if (direc.Z > 2.0f) 2714 if (direc.Z > 2.0f)
2308 { 2715 {
2309 direc.Z *= 3.0f; 2716 if(m_animator.m_animTickJump == -1)
2310 2717 {
2311 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2718 direc.Z *= 3.0f; // jump
2312 Animator.TrySetMovementAnimation("PREJUMP"); 2719 }
2313 Animator.TrySetMovementAnimation("JUMP"); 2720 else
2721 {
2722 direc.Z *= 0.1f; // prejump
2723 }
2724 / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2725 Animator.TrySetMovementAnimation("PREJUMP");
2726 Animator.TrySetMovementAnimation("JUMP");
2727 * /
2314 } 2728 }
2315 } 2729 } */
2316 } 2730 }
2317 2731
2318 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2732 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2319 m_forceToApply = direc; 2733 m_forceToApply = direc;
2320 2734 m_isNudging = Nudging;
2321 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2735 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2322 } 2736 }
2323 2737
@@ -2366,6 +2780,9 @@ namespace OpenSim.Region.Framework.Scenes
2366 2780
2367 CheckForSignificantMovement(); // sends update to the modules. 2781 CheckForSignificantMovement(); // sends update to the modules.
2368 } 2782 }
2783
2784 //Sending prim updates AFTER the avatar terse updates are sent
2785 SendPrimUpdates();
2369 } 2786 }
2370 2787
2371 #endregion 2788 #endregion
@@ -3180,6 +3597,7 @@ namespace OpenSim.Region.Framework.Scenes
3180 m_callbackURI = cAgent.CallbackURI; 3597 m_callbackURI = cAgent.CallbackURI;
3181 3598
3182 m_pos = cAgent.Position; 3599 m_pos = cAgent.Position;
3600
3183 m_velocity = cAgent.Velocity; 3601 m_velocity = cAgent.Velocity;
3184 m_CameraCenter = cAgent.Center; 3602 m_CameraCenter = cAgent.Center;
3185 m_CameraAtAxis = cAgent.AtAxis; 3603 m_CameraAtAxis = cAgent.AtAxis;
@@ -3268,17 +3686,45 @@ namespace OpenSim.Region.Framework.Scenes
3268 /// </summary> 3686 /// </summary>
3269 public override void UpdateMovement() 3687 public override void UpdateMovement()
3270 { 3688 {
3271 if (m_forceToApply.HasValue) 3689 if (Animator!=null) // add for jumping
3272 { 3690 { // add for jumping
3273 Vector3 force = m_forceToApply.Value; 3691 // if (!m_animator.m_jumping) // add for jumping
3274 3692 // { // add for jumping
3275 m_updateflag = true;
3276 3693
3277 Velocity = force; 3694 if (m_forceToApply.HasValue) // this section realigned
3695 {
3278 3696
3279 m_forceToApply = null; 3697 Vector3 force = m_forceToApply.Value;
3280 } 3698 m_updateflag = true;
3281 } 3699if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3700 Velocity = force;
3701//Console.WriteLine("UM1 {0}", Velocity);
3702 m_forceToApply = null;
3703 }
3704 else
3705 {
3706 if (m_isNudging)
3707 {
3708 Vector3 force = Vector3.Zero;
3709
3710 m_updateflag = true;
3711if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3712 Velocity = force;
3713//Console.WriteLine("UM2 {0}", Velocity);
3714 m_isNudging = false;
3715 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3716 }
3717 else // add for jumping
3718 { // add for jumping
3719 Vector3 force = Vector3.Zero; // add for jumping
3720if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3721//Console.WriteLine("UM3 {0}", Velocity);
3722 Velocity = force; // add for jumping
3723 }
3724 }
3725 // } // end realign
3726 } // add for jumping
3727 } // add for jumping
3282 3728
3283 /// <summary> 3729 /// <summary>
3284 /// Adds a physical representation of the avatar to the Physics plugin 3730 /// Adds a physical representation of the avatar to the Physics plugin
@@ -3292,10 +3738,8 @@ namespace OpenSim.Region.Framework.Scenes
3292 3738
3293 Vector3 pVec = AbsolutePosition; 3739 Vector3 pVec = AbsolutePosition;
3294 3740
3295 // Old bug where the height was in centimeters instead of meters 3741 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3296 m_physicsActor = scene.AddAvatar(LocalId, Firstname + "." + Lastname, pVec,
3297 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3742 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3298
3299 scene.AddPhysicsActorTaint(m_physicsActor); 3743 scene.AddPhysicsActorTaint(m_physicsActor);
3300 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3744 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3301 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3745 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3319,18 +3763,29 @@ namespace OpenSim.Region.Framework.Scenes
3319 { 3763 {
3320 if (e == null) 3764 if (e == null)
3321 return; 3765 return;
3322 3766
3323 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3767 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3324 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3325 // as of this comment the interval is set in AddToPhysicalScene 3768 // as of this comment the interval is set in AddToPhysicalScene
3326 if (Animator!=null) 3769 if (Animator!=null)
3327 Animator.UpdateMovementAnimations(); 3770 {
3771 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3772 { // else its will lock out other animation changes, like ground sit.
3773 Animator.UpdateMovementAnimations();
3774 m_updateCount--;
3775 }
3776 }
3328 3777
3329 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3778 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3330 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3779 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3331 3780
3332 CollisionPlane = Vector4.UnitW; 3781 CollisionPlane = Vector4.UnitW;
3333 3782
3783 if (m_lastColCount != coldata.Count)
3784 {
3785 m_updateCount = UPDATE_COUNT;
3786 m_lastColCount = coldata.Count;
3787 }
3788
3334 if (coldata.Count != 0 && Animator != null) 3789 if (coldata.Count != 0 && Animator != null)
3335 { 3790 {
3336 switch (Animator.CurrentMovementAnimation) 3791 switch (Animator.CurrentMovementAnimation)
@@ -3360,6 +3815,148 @@ namespace OpenSim.Region.Framework.Scenes
3360 } 3815 }
3361 } 3816 }
3362 3817
3818 List<uint> thisHitColliders = new List<uint>();
3819 List<uint> endedColliders = new List<uint>();
3820 List<uint> startedColliders = new List<uint>();
3821
3822 foreach (uint localid in coldata.Keys)
3823 {
3824 thisHitColliders.Add(localid);
3825 if (!m_lastColliders.Contains(localid))
3826 {
3827 startedColliders.Add(localid);
3828 }
3829 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3830 }
3831
3832 // calculate things that ended colliding
3833 foreach (uint localID in m_lastColliders)
3834 {
3835 if (!thisHitColliders.Contains(localID))
3836 {
3837 endedColliders.Add(localID);
3838 }
3839 }
3840 //add the items that started colliding this time to the last colliders list.
3841 foreach (uint localID in startedColliders)
3842 {
3843 m_lastColliders.Add(localID);
3844 }
3845 // remove things that ended colliding from the last colliders list
3846 foreach (uint localID in endedColliders)
3847 {
3848 m_lastColliders.Remove(localID);
3849 }
3850
3851 // do event notification
3852 if (startedColliders.Count > 0)
3853 {
3854 ColliderArgs StartCollidingMessage = new ColliderArgs();
3855 List<DetectedObject> colliding = new List<DetectedObject>();
3856 foreach (uint localId in startedColliders)
3857 {
3858 if (localId == 0)
3859 continue;
3860
3861 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3862 string data = "";
3863 if (obj != null)
3864 {
3865 DetectedObject detobj = new DetectedObject();
3866 detobj.keyUUID = obj.UUID;
3867 detobj.nameStr = obj.Name;
3868 detobj.ownerUUID = obj.OwnerID;
3869 detobj.posVector = obj.AbsolutePosition;
3870 detobj.rotQuat = obj.GetWorldRotation();
3871 detobj.velVector = obj.Velocity;
3872 detobj.colliderType = 0;
3873 detobj.groupUUID = obj.GroupID;
3874 colliding.Add(detobj);
3875 }
3876 }
3877
3878 if (colliding.Count > 0)
3879 {
3880 StartCollidingMessage.Colliders = colliding;
3881
3882 foreach (SceneObjectGroup att in Attachments)
3883 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3884 }
3885 }
3886
3887 if (endedColliders.Count > 0)
3888 {
3889 ColliderArgs EndCollidingMessage = new ColliderArgs();
3890 List<DetectedObject> colliding = new List<DetectedObject>();
3891 foreach (uint localId in endedColliders)
3892 {
3893 if (localId == 0)
3894 continue;
3895
3896 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3897 string data = "";
3898 if (obj != null)
3899 {
3900 DetectedObject detobj = new DetectedObject();
3901 detobj.keyUUID = obj.UUID;
3902 detobj.nameStr = obj.Name;
3903 detobj.ownerUUID = obj.OwnerID;
3904 detobj.posVector = obj.AbsolutePosition;
3905 detobj.rotQuat = obj.GetWorldRotation();
3906 detobj.velVector = obj.Velocity;
3907 detobj.colliderType = 0;
3908 detobj.groupUUID = obj.GroupID;
3909 colliding.Add(detobj);
3910 }
3911 }
3912
3913 if (colliding.Count > 0)
3914 {
3915 EndCollidingMessage.Colliders = colliding;
3916
3917 foreach (SceneObjectGroup att in Attachments)
3918 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
3919 }
3920 }
3921
3922 if (thisHitColliders.Count > 0)
3923 {
3924 ColliderArgs CollidingMessage = new ColliderArgs();
3925 List<DetectedObject> colliding = new List<DetectedObject>();
3926 foreach (uint localId in thisHitColliders)
3927 {
3928 if (localId == 0)
3929 continue;
3930
3931 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3932 string data = "";
3933 if (obj != null)
3934 {
3935 DetectedObject detobj = new DetectedObject();
3936 detobj.keyUUID = obj.UUID;
3937 detobj.nameStr = obj.Name;
3938 detobj.ownerUUID = obj.OwnerID;
3939 detobj.posVector = obj.AbsolutePosition;
3940 detobj.rotQuat = obj.GetWorldRotation();
3941 detobj.velVector = obj.Velocity;
3942 detobj.colliderType = 0;
3943 detobj.groupUUID = obj.GroupID;
3944 colliding.Add(detobj);
3945 }
3946 }
3947
3948 if (colliding.Count > 0)
3949 {
3950 CollidingMessage.Colliders = colliding;
3951
3952 lock (m_attachments)
3953 {
3954 foreach (SceneObjectGroup att in m_attachments)
3955 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
3956 }
3957 }
3958 }
3959
3363 if (m_invulnerable) 3960 if (m_invulnerable)
3364 return; 3961 return;
3365 3962
@@ -3444,6 +4041,10 @@ namespace OpenSim.Region.Framework.Scenes
3444 { 4041 {
3445 lock (m_attachments) 4042 lock (m_attachments)
3446 { 4043 {
4044 // This may be true when the attachment comes back
4045 // from serialization after login. Clear it.
4046 gobj.IsDeleted = false;
4047
3447 m_attachments.Add(gobj); 4048 m_attachments.Add(gobj);
3448 } 4049 }
3449 } 4050 }
@@ -3785,6 +4386,39 @@ namespace OpenSim.Region.Framework.Scenes
3785 return; 4386 return;
3786 } 4387 }
3787 4388
4389 XmlDocument doc = new XmlDocument();
4390 string stateData = String.Empty;
4391
4392 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4393 if (attServ != null)
4394 {
4395 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4396 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4397 if (stateData != String.Empty)
4398 {
4399 try
4400 {
4401 doc.LoadXml(stateData);
4402 }
4403 catch { }
4404 }
4405 }
4406
4407 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4408
4409 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4410 if (nodes.Count > 0)
4411 {
4412 foreach (XmlNode n in nodes)
4413 {
4414 XmlElement elem = (XmlElement)n;
4415 string itemID = elem.GetAttribute("ItemID");
4416 string xml = elem.InnerXml;
4417
4418 itemData[new UUID(itemID)] = xml;
4419 }
4420 }
4421
3788 List<AvatarAttachment> attachments = m_appearance.GetAttachments(); 4422 List<AvatarAttachment> attachments = m_appearance.GetAttachments();
3789 foreach (AvatarAttachment attach in attachments) 4423 foreach (AvatarAttachment attach in attachments)
3790 { 4424 {
@@ -3805,7 +4439,30 @@ namespace OpenSim.Region.Framework.Scenes
3805 4439
3806 try 4440 try
3807 { 4441 {
3808 m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p); 4442 string xmlData;
4443 XmlDocument d = new XmlDocument();
4444 UUID asset;
4445 if (itemData.TryGetValue(itemID, out xmlData))
4446 {
4447 d.LoadXml(xmlData);
4448 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4449
4450 // Rez from inventory
4451 asset
4452 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4453
4454 }
4455 else
4456 {
4457 // Rez from inventory (with a null doc to let
4458 // CHANGED_OWNER happen)
4459 asset
4460 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4461 }
4462
4463 m_log.InfoFormat(
4464 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}",
4465 p, itemID, asset);
3809 } 4466 }
3810 catch (Exception e) 4467 catch (Exception e)
3811 { 4468 {
@@ -3838,6 +4495,15 @@ namespace OpenSim.Region.Framework.Scenes
3838 m_reprioritization_called = false; 4495 m_reprioritization_called = false;
3839 } 4496 }
3840 } 4497 }
4498
4499 private Vector3 Quat2Euler(Quaternion rot){
4500 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4501 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4502 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4503 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4504 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4505 return(new Vector3(x,y,z));
4506 }
3841 4507
3842 public void SaveChangedAttachments() 4508 public void SaveChangedAttachments()
3843 { 4509 {
@@ -3861,5 +4527,30 @@ namespace OpenSim.Region.Framework.Scenes
3861 } 4527 }
3862 } 4528 }
3863 } 4529 }
4530
4531 private void CheckLandingPoint(ref Vector3 pos)
4532 {
4533 // Never constrain lures
4534 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
4535 return;
4536
4537 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
4538 return;
4539
4540 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
4541
4542 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
4543 land.LandData.UserLocation != Vector3.Zero &&
4544 land.LandData.OwnerID != m_uuid &&
4545 (!m_scene.Permissions.IsGod(m_uuid)) &&
4546 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)))
4547 {
4548 float curr = Vector3.Distance(AbsolutePosition, pos);
4549 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
4550 pos = land.LandData.UserLocation;
4551 else
4552 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
4553 }
4554 }
3864 } 4555 }
3865} 4556}
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 fcf7e0c..9174070 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 }
@@ -236,7 +236,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
236 if (originalLinkNum != 0) 236 if (originalLinkNum != 0)
237 part.LinkNum = originalLinkNum; 237 part.LinkNum = originalLinkNum;
238 238
239 part.StoreUndoState(); 239 part.StoreUndoState(UndoType.STATE_ALL);
240 reader.Close(); 240 reader.Close();
241 sr.Close(); 241 sr.Close();
242 } 242 }
@@ -345,6 +345,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
345 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 345 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
346 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 346 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
347 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 347 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
348
349 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
348 #endregion 350 #endregion
349 351
350 #region TaskInventoryXmlProcessors initialization 352 #region TaskInventoryXmlProcessors initialization
@@ -734,6 +736,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
734 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 736 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
735 } 737 }
736 738
739 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
740 {
741 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
742 }
743
737 #endregion 744 #endregion
738 745
739 #region TaskInventoryXmlProcessors 746 #region TaskInventoryXmlProcessors
@@ -1216,6 +1223,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1216 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1223 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1217 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1224 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1218 1225
1226 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1227
1219 writer.WriteEndElement(); 1228 writer.WriteEndElement();
1220 } 1229 }
1221 1230
@@ -1500,12 +1509,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1500 { 1509 {
1501 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1510 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1502 1511
1503 if (reader.IsEmptyElement)
1504 {
1505 reader.Read();
1506 return tinv;
1507 }
1508
1509 reader.ReadStartElement(name, String.Empty); 1512 reader.ReadStartElement(name, String.Empty);
1510 1513
1511 while (reader.Name == "TaskInventoryItem") 1514 while (reader.Name == "TaskInventoryItem")
@@ -1548,12 +1551,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1548 1551
1549 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1552 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1550 1553
1551 if (reader.IsEmptyElement)
1552 {
1553 reader.Read();
1554 return shape;
1555 }
1556
1557 reader.ReadStartElement(name, String.Empty); // Shape 1554 reader.ReadStartElement(name, String.Empty); // Shape
1558 1555
1559 string nodeName = string.Empty; 1556 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;