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.cs342
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Permissions.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs542
-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.cs225
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs7
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs911
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs215
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs758
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs1231
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs76
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
29 files changed, 3709 insertions, 1042 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index dd11ded..6bbdd7d 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;
@@ -101,6 +102,10 @@ namespace OpenSim.Region.Framework.Interfaces
101 ISceneEntity RezSingleAttachmentFromInventory( 102 ISceneEntity RezSingleAttachmentFromInventory(
102 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus); 103 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus);
103 104
105 // Same as above, but also load script states from a separate doc
106 UUID RezSingleAttachmentFromInventory(
107 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
108
104 /// <summary> 109 /// <summary>
105 /// Rez multiple attachments from a user's inventory 110 /// Rez multiple attachments from a user's inventory
106 /// </summary> 111 /// </summary>
@@ -133,18 +138,15 @@ namespace OpenSim.Region.Framework.Interfaces
133 /// <summary> 138 /// <summary>
134 /// Detach the given item so that it remains in the user's inventory. 139 /// Detach the given item so that it remains in the user's inventory.
135 /// </summary> 140 /// </summary>
136 /// <param name="itemID">/param> 141 /// <param name="itemID">
137 /// <param name="remoteClient"></param> 142 /// A <see cref="UUID"/>
143 /// </param>
144 /// <param name="remoteClient">
145 /// A <see cref="IClientAPI"/>
146 /// </param>
138 void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient); 147 void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient);
139 148
140 /// <summary> 149 /// <summary>
141 /// Update the position of an attachment.
142 /// </summary>
143 /// <param name="sog"></param>
144 /// <param name="pos"></param>
145 void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos);
146
147 /// <summary>
148 /// Update the user inventory with a changed attachment 150 /// Update the user inventory with a changed attachment
149 /// </summary> 151 /// </summary>
150 /// <param name="remoteClient"></param> 152 /// <param name="remoteClient"></param>
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 e07d8b4..4925175 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -57,11 +57,17 @@ namespace OpenSim.Region.Framework.Scenes.Animation
57 { 57 {
58 get { return m_movementAnimation; } 58 get { return m_movementAnimation; }
59 } 59 }
60 protected string m_movementAnimation = "DEFAULT"; 60 // protected string m_movementAnimation = "DEFAULT"; //KF: 'DEFAULT' does not exist!
61 61 protected string m_movementAnimation = "CROUCH"; //KF: CROUCH ensures reliable Av Anim. init.
62 private int m_animTickFall; 62 private int m_animTickFall;
63 private int m_animTickJump; 63// private int m_animTickJump;
64 64 public int m_animTickJump; // ScenePresence has to see this to control +Z force
65 public bool m_jumping = false; // Add for jumping
66 public float m_jumpVelocity = 0f; // Add for jumping
67 private int m_landing = 0; // Add for jumping
68 public bool m_falling = false; // Add for falling
69 private float m_fallHeight; // Add for falling
70
65 /// <value> 71 /// <value>
66 /// The scene presence that this animator applies to 72 /// The scene presence that this animator applies to
67 /// </value> 73 /// </value>
@@ -122,7 +128,9 @@ namespace OpenSim.Region.Framework.Scenes.Animation
122 128
123 public void ResetAnimations() 129 public void ResetAnimations()
124 { 130 {
131Console.WriteLine("ResetA.............");
125 m_animations.Clear(); 132 m_animations.Clear();
133TrySetMovementAnimation("STAND");
126 } 134 }
127 135
128 /// <summary> 136 /// <summary>
@@ -152,14 +160,14 @@ namespace OpenSim.Region.Framework.Scenes.Animation
152 /// </summary> 160 /// </summary>
153 public string GetMovementAnimation() 161 public string GetMovementAnimation()
154 { 162 {
155 const float FALL_DELAY = 0.33f; 163//Console.WriteLine("GMA-------"); //##
156 const float PREJUMP_DELAY = 0.25f; 164//#@ const float FALL_DELAY = 0.33f;
157 165 const float FALL_DELAY = 800f; //## mS
166//rm for jumping const float PREJUMP_DELAY = 0.25f;
167 const float PREJUMP_DELAY = 200f; // mS add for jumping
168 const float JUMP_PERIOD = 800f; // mS add for jumping
158 #region Inputs 169 #region Inputs
159 if (m_scenePresence.SitGround) 170
160 {
161 return "SIT_GROUND_CONSTRAINED";
162 }
163 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags; 171 AgentManager.ControlFlags controlFlags = (AgentManager.ControlFlags)m_scenePresence.AgentControlFlags;
164 PhysicsActor actor = m_scenePresence.PhysicsActor; 172 PhysicsActor actor = m_scenePresence.PhysicsActor;
165 173
@@ -169,11 +177,10 @@ namespace OpenSim.Region.Framework.Scenes.Animation
169 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); 177 Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix);
170 178
171 // Check control flags 179 // Check control flags
172 bool heldForward = 180 bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS);
173 (((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) || ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS)); 181 bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
174 bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; 182 bool heldLeft = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
175 bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; 183 bool heldRight = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG);
176 bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG;
177 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; 184 //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT;
178 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT; 185 //bool heldTurnRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT;
179 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS; 186 bool heldUp = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) == AgentManager.ControlFlags.AGENT_CONTROL_UP_POS;
@@ -192,8 +199,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
192 199
193 // Is the avatar trying to move? 200 // Is the avatar trying to move?
194// bool moving = (move != Vector3.Zero); 201// bool moving = (move != Vector3.Zero);
195 bool jumping = m_animTickJump != 0; 202// rm for jumping bool jumping = m_animTickJump != 0;
196
197 #endregion Inputs 203 #endregion Inputs
198 204
199 #region Flying 205 #region Flying
@@ -202,6 +208,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
202 { 208 {
203 m_animTickFall = 0; 209 m_animTickFall = 0;
204 m_animTickJump = 0; 210 m_animTickJump = 0;
211 m_jumping = false; //add for jumping
212 m_falling = true; //add for falling
213 m_jumpVelocity = 0f; //add for jumping
214 actor.Selected = false; //add for jumping flag
215 m_fallHeight = actor.Position.Z; // save latest flying height
205 216
206 if (move.X != 0f || move.Y != 0f) 217 if (move.X != 0f || move.Y != 0f)
207 { 218 {
@@ -213,8 +224,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation
213 } 224 }
214 else if (move.Z < 0f) 225 else if (move.Z < 0f)
215 { 226 {
216 if (actor != null && actor.IsColliding) 227 if (actor != null && actor.IsColliding)
228 { //##
229//Console.WriteLine("LAND FLYING"); // ##
217 return "LAND"; 230 return "LAND";
231 } //#
218 else 232 else
219 return "HOVER_DOWN"; 233 return "HOVER_DOWN";
220 } 234 }
@@ -228,48 +242,127 @@ namespace OpenSim.Region.Framework.Scenes.Animation
228 242
229 #region Falling/Floating/Landing 243 #region Falling/Floating/Landing
230 244
231 if (actor == null || !actor.IsColliding) 245// rm for jumping if (actor == null || !actor.IsColliding)
246 if ((actor == null || !actor.IsColliding) && !m_jumping) // add for jumping
232 { 247 {
233 float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 248// rm float fallElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
249 float fallElapsed = (float)(Environment.TickCount - m_animTickFall); // add, in mS
234 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; 250 float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f;
251//Console.WriteLine("falling t={0} v={1}", fallElapsed, fallVelocity); //##
235 252
236 if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f)) 253// rm for fall if (m_animTickFall == 0 || (fallElapsed > FALL_DELAY && fallVelocity >= 0.0f))
254 if (!m_jumping && (fallVelocity < -3.0f) ) m_falling = true; // add for falling and jumping
255
256 if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) // add for jumping
257 // not falling yet or going up
237 { 258 {
238 // Just started falling 259 // reset start of fall time
239 m_animTickFall = Environment.TickCount; 260 m_animTickFall = Environment.TickCount;
240 } 261 }
241 else if (!jumping && fallElapsed > FALL_DELAY) 262// else if (!jumping && fallElapsed > FALL_DELAY)
263 else if (!m_jumping && (fallElapsed > FALL_DELAY) && (fallVelocity < -3.0f) && (m_scenePresence.m_wasFlying)) // add for falling and jumping
242 { 264 {
243 // Falling long enough to trigger the animation 265 // Falling long enough to trigger the animation
266//Console.WriteLine("FALLDOWN"); //##
244 return "FALLDOWN"; 267 return "FALLDOWN";
245 } 268 }
246 else if (m_animTickJump == -1)
247 {
248 m_animTickJump = 0;
249 return "STAND";
250 }
251 269
252 return m_movementAnimation; 270 return m_movementAnimation;
253 } 271 }
254 272
255 #endregion Falling/Floating/Landing 273 #endregion Falling/Floating/Landing
256 274
275
276 #region Jumping // section added for jumping...
277
278 int jumptime;
279 jumptime = Environment.TickCount - m_animTickJump;
280
281
282 if ((move.Z > 0f) && (!m_jumping))
283 {
284//Console.WriteLine("PJ {0}", jumptime); //##
285 // Start jumping, prejump
286 m_animTickFall = 0;
287 m_jumping = true;
288 m_falling = false;
289 actor.Selected = true; // borrowed for jmping flag
290 m_animTickJump = Environment.TickCount;
291 m_jumpVelocity = 0.35f;
292 return "PREJUMP";
293 }
294
295 if(m_jumping)
296 {
297 if ( (jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding)
298 {
299//Console.WriteLine("LA {0}", jumptime); //##
300 // end jumping
301 m_jumping = false;
302 m_falling = false;
303 actor.Selected = false; // borrowed for jumping flag
304 m_jumpVelocity = 0f;
305 m_animTickFall = Environment.TickCount;
306 return "LAND";
307 }
308 else if (jumptime > JUMP_PERIOD)
309 {
310//Console.WriteLine("JD {0}", jumptime); //##
311 // jump down
312 m_jumpVelocity = 0f;
313 return "JUMP";
314 }
315 else if (jumptime > PREJUMP_DELAY)
316 {
317//Console.WriteLine("JU {0}", jumptime); //##
318 // jump up
319 m_jumping = true;
320 m_jumpVelocity = 10f;
321 return "JUMP";
322 }
323 }
324
325 #endregion Jumping // end added section
326
257 #region Ground Movement 327 #region Ground Movement
258 328
259 if (m_movementAnimation == "FALLDOWN") 329 if (m_movementAnimation == "FALLDOWN")
260 { 330 {
331 m_falling = false;
261 m_animTickFall = Environment.TickCount; 332 m_animTickFall = Environment.TickCount;
262
263 // TODO: SOFT_LAND support 333 // TODO: SOFT_LAND support
264 return "LAND"; 334 float fallHeight = m_fallHeight - actor.Position.Z;
335//Console.WriteLine("Hit from {0}", fallHeight); //##
336 if (fallHeight > 15.0f) // add for falling
337 return "STANDUP";
338 else if (fallHeight > 8.0f) // add for falling
339 return "SOFT_LAND"; // add for falling
340 else // add for falling
341 return "LAND"; // add for falling
265 } 342 }
266 else if (m_movementAnimation == "LAND") 343// rm jumping float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f;
344// rm jumping if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY))
345// rm for landing return "LAND";
346 else if ((m_movementAnimation == "LAND") || (m_movementAnimation == "SOFT_LAND") || (m_movementAnimation == "STANDUP"))
267 { 347 {
268 float landElapsed = (float)(Environment.TickCount - m_animTickFall) / 1000f; 348 int landElapsed = Environment.TickCount - m_animTickFall; // add for jumping
269 if ((m_animTickFall != 0) && (landElapsed <= FALL_DELAY)) 349 int limit = 1000; // add for jumping
270 return "LAND"; 350 if(m_movementAnimation == "LAND") limit = 350; // add for jumping
271 } 351 // NB if the above is set too long a weird anim reset from some place prevents STAND from being sent to client
272 352
353 if ((m_animTickFall != 0) && (landElapsed <= limit)) // add for jumping
354 {
355//Console.WriteLine("Lelapse {0}", m_movementAnimation); //##
356 return m_movementAnimation;
357 }
358 else
359 {
360//Console.WriteLine("end/STAND"); //##
361 m_fallHeight = actor.Position.Z; // save latest flying height
362 return "STAND";
363 }
364 }
365/* This section removed, replaced by jumping section
273 m_animTickFall = 0; 366 m_animTickFall = 0;
274 367
275 if (move.Z > 0.2f) 368 if (move.Z > 0.2f)
@@ -281,7 +374,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation
281 m_animTickJump = Environment.TickCount; 374 m_animTickJump = Environment.TickCount;
282 return "PREJUMP"; 375 return "PREJUMP";
283 } 376 }
284 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 1000.0f) 377 else if (Environment.TickCount - m_animTickJump > PREJUMP_DELAY * 800.0f)
285 { 378 {
286 // Start actual jump 379 // Start actual jump
287 if (m_animTickJump == -1) 380 if (m_animTickJump == -1)
@@ -294,37 +387,40 @@ namespace OpenSim.Region.Framework.Scenes.Animation
294 m_animTickJump = -1; 387 m_animTickJump = -1;
295 return "JUMP"; 388 return "JUMP";
296 } 389 }
297 else
298 return "JUMP";
299 } 390 }
300 else 391 else
301 { 392 {
302 // Not jumping 393 // Not jumping
303 m_animTickJump = 0; 394 m_animTickJump = 0;
304 395 */
305 if (move.X != 0f || move.Y != 0f) 396 // next section moved outside paren. and realigned for jumping
306 { 397 if (move.X != 0f || move.Y != 0f)
307 // Walking / crouchwalking / running 398 {
308 if (move.Z < 0) 399 m_fallHeight = actor.Position.Z; // save latest flying height
309 return "CROUCHWALK"; 400 m_falling = false; // Add for falling
310 else if (m_scenePresence.SetAlwaysRun) 401 // Walking / crouchwalking / running
311 return "RUN"; 402 if (move.Z < 0f)
312 else 403 return "CROUCHWALK";
313 return "WALK"; 404 else if (m_scenePresence.SetAlwaysRun)
314 } 405 return "RUN";
315 else 406 else
316 { 407 return "WALK";
317 // Not walking
318 if (move.Z < 0)
319 return "CROUCH";
320 else
321 return "STAND";
322 }
323 } 408 }
324 409// rm for jumping else
410 else if (!m_jumping) // add for jumping
411 {
412 m_falling = false; // Add for falling
413 // Not walking
414 if (move.Z < 0f)
415 return "CROUCH";
416 else
417 return "STAND";
418 }
419 // end section realign for jumping
325 #endregion Ground Movement 420 #endregion Ground Movement
326 421
327 //return m_movementAnimation; 422 m_falling = false; // Add for falling
423 return m_movementAnimation;
328 } 424 }
329 425
330 /// <summary> 426 /// <summary>
@@ -333,9 +429,15 @@ namespace OpenSim.Region.Framework.Scenes.Animation
333 public void UpdateMovementAnimations() 429 public void UpdateMovementAnimations()
334 { 430 {
335 m_movementAnimation = GetMovementAnimation(); 431 m_movementAnimation = GetMovementAnimation();
336// m_log.DebugFormat( 432/* if (m_movementAnimation == "PREJUMP" && !m_scenePresence.Scene.m_usePreJump)
337// "[SCENE PRESENCE ANIMATOR]: Got animation {0} for {1}", m_movementAnimation, m_scenePresence.Name); 433 {
338 TrySetMovementAnimation(m_movementAnimation); 434 // This was the previous behavior before PREJUMP
435 TrySetMovementAnimation("JUMP");
436 }
437 else
438 { removed for jumping */
439 TrySetMovementAnimation(m_movementAnimation);
440// rm for jumping }
339 } 441 }
340 442
341 public UUID[] GetAnimationArray() 443 public UUID[] GetAnimationArray()
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 3423542..088839d 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -104,8 +104,15 @@ namespace OpenSim.Region.Framework.Scenes
104 // better than losing the object for now. 104 // better than losing the object for now.
105 if (permissionToDelete) 105 if (permissionToDelete)
106 { 106 {
107 List<uint> killIDs = new List<uint>();
108
107 foreach (SceneObjectGroup g in objectGroups) 109 foreach (SceneObjectGroup g in objectGroups)
110 {
111 killIDs.Add(g.LocalId);
108 g.DeleteGroupFromScene(false); 112 g.DeleteGroupFromScene(false);
113 }
114
115 m_scene.SendKillObject(killIDs);
109 } 116 }
110 } 117 }
111 118
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 96da2c3..65c6a29 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -55,8 +55,12 @@ namespace OpenSim.Region.Framework.Scenes
55 55
56 public delegate void OnTerrainTickDelegate(); 56 public delegate void OnTerrainTickDelegate();
57 57
58 public delegate void OnTerrainUpdateDelegate();
59
58 public event OnTerrainTickDelegate OnTerrainTick; 60 public event OnTerrainTickDelegate OnTerrainTick;
59 61
62 public event OnTerrainUpdateDelegate OnTerrainUpdate;
63
60 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 64 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
61 65
62 public event OnBackupDelegate OnBackup; 66 public event OnBackupDelegate OnBackup;
@@ -775,6 +779,26 @@ namespace OpenSim.Region.Framework.Scenes
775 } 779 }
776 } 780 }
777 } 781 }
782 public void TriggerTerrainUpdate()
783 {
784 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
785 if (handlerTerrainUpdate != null)
786 {
787 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
788 {
789 try
790 {
791 d();
792 }
793 catch (Exception e)
794 {
795 m_log.ErrorFormat(
796 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
797 e.Message, e.StackTrace);
798 }
799 }
800 }
801 }
778 802
779 public void TriggerTerrainTick() 803 public void TriggerTerrainTick()
780 { 804 {
diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
index 1b10e3c..0a34a4c 100644
--- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs
+++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs
@@ -157,7 +157,7 @@ namespace OpenSim.Region.Framework.Scenes
157 157
158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity) 158 private uint GetPriorityByBestAvatarResponsiveness(IClientAPI client, ISceneEntity entity)
159 { 159 {
160 uint pqueue = ComputeDistancePriority(client,entity,true); 160 uint pqueue = ComputeDistancePriority(client,entity,false);
161 161
162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId); 162 ScenePresence presence = m_scene.GetScenePresence(client.AgentId);
163 if (presence != null) 163 if (presence != null)
@@ -226,7 +226,7 @@ namespace OpenSim.Region.Framework.Scenes
226 226
227 for (int i = 0; i < queues - 1; i++) 227 for (int i = 0; i < queues - 1; i++)
228 { 228 {
229 if (distance < 10 * Math.Pow(2.0,i)) 229 if (distance < 30 * Math.Pow(2.0,i))
230 break; 230 break;
231 pqueue++; 231 pqueue++;
232 } 232 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 4700c3b..89f3683 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -104,34 +104,22 @@ namespace OpenSim.Region.Framework.Scenes
104 /// <param name="item"></param> 104 /// <param name="item"></param>
105 public bool AddInventoryItem(InventoryItemBase item) 105 public bool AddInventoryItem(InventoryItemBase item)
106 { 106 {
107 if (UUID.Zero == item.Folder) 107 InventoryFolderBase folder;
108
109 if (item.Folder == UUID.Zero)
108 { 110 {
109 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 111 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
110 if (f != null) 112 if (folder == null)
111 {
112// m_log.DebugFormat(
113// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}",
114// f.Name, (AssetType)f.Type, item.Name);
115
116 item.Folder = f.ID;
117 }
118 else
119 { 113 {
120 f = InventoryService.GetRootFolder(item.Owner); 114 folder = InventoryService.GetRootFolder(item.Owner);
121 if (f != null) 115
122 { 116 if (folder == null)
123 item.Folder = f.ID;
124 }
125 else
126 {
127 m_log.WarnFormat(
128 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
129 item.Owner, item.Name);
130 return false; 117 return false;
131 }
132 } 118 }
119
120 item.Folder = folder.ID;
133 } 121 }
134 122
135 if (InventoryService.AddItem(item)) 123 if (InventoryService.AddItem(item))
136 { 124 {
137 int userlevel = 0; 125 int userlevel = 0;
@@ -251,8 +239,7 @@ namespace OpenSim.Region.Framework.Scenes
251 239
252 // Update item with new asset 240 // Update item with new asset
253 item.AssetID = asset.FullID; 241 item.AssetID = asset.FullID;
254 if (group.UpdateInventoryItem(item)) 242 group.UpdateInventoryItem(item);
255 remoteClient.SendAgentAlertMessage("Script saved", false);
256 243
257 part.GetProperties(remoteClient); 244 part.GetProperties(remoteClient);
258 245
@@ -263,12 +250,7 @@ namespace OpenSim.Region.Framework.Scenes
263 { 250 {
264 // Needs to determine which engine was running it and use that 251 // Needs to determine which engine was running it and use that
265 // 252 //
266 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 253 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
267 errors = part.Inventory.GetScriptErrors(item.ItemID);
268 }
269 else
270 {
271 remoteClient.SendAgentAlertMessage("Script saved", false);
272 } 254 }
273 part.ParentGroup.ResumeScripts(); 255 part.ParentGroup.ResumeScripts();
274 return errors; 256 return errors;
@@ -327,6 +309,7 @@ namespace OpenSim.Region.Framework.Scenes
327 { 309 {
328 if (UUID.Zero == transactionID) 310 if (UUID.Zero == transactionID)
329 { 311 {
312 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
330 item.Name = itemUpd.Name; 313 item.Name = itemUpd.Name;
331 item.Description = itemUpd.Description; 314 item.Description = itemUpd.Description;
332 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 315 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
@@ -705,6 +688,8 @@ namespace OpenSim.Region.Framework.Scenes
705 return; 688 return;
706 } 689 }
707 690
691 if (newName == null) newName = item.Name;
692
708 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 693 AssetBase asset = AssetService.Get(item.AssetID.ToString());
709 694
710 if (asset != null) 695 if (asset != null)
@@ -761,6 +746,24 @@ namespace OpenSim.Region.Framework.Scenes
761 } 746 }
762 747
763 /// <summary> 748 /// <summary>
749 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
750 /// </summary>
751 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
752 {
753 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
754 foreach (InventoryItemBase b in items)
755 {
756 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
757 InventoryItemBase n = InventoryService.GetItem(b);
758 n.Folder = destfolder;
759 moveitems.Add(n);
760 remoteClient.SendInventoryItemCreateUpdate(n, 0);
761 }
762
763 MoveInventoryItem(remoteClient, moveitems);
764 }
765
766 /// <summary>
764 /// Move an item within the agent's inventory. 767 /// Move an item within the agent's inventory.
765 /// </summary> 768 /// </summary>
766 /// <param name="remoteClient"></param> 769 /// <param name="remoteClient"></param>
@@ -961,16 +964,19 @@ namespace OpenSim.Region.Framework.Scenes
961 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) 964 public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID)
962 { 965 {
963 SceneObjectPart part = GetSceneObjectPart(localID); 966 SceneObjectPart part = GetSceneObjectPart(localID);
964 if (part == null) 967 SceneObjectGroup group = null;
965 return; 968 if (part != null)
966 969 {
967 SceneObjectGroup group = part.ParentGroup; 970 group = part.ParentGroup;
968 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) 971 }
969 return; 972 if (part != null && group != null)
970 973 {
971 TaskInventoryItem item = group.GetInventoryItem(localID, itemID); 974 if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId))
972 if (item == null) 975 return;
973 return; 976
977 TaskInventoryItem item = group.GetInventoryItem(localID, itemID);
978 if (item == null)
979 return;
974 980
975 if (item.Type == 10) 981 if (item.Type == 10)
976 { 982 {
@@ -1190,6 +1196,10 @@ namespace OpenSim.Region.Framework.Scenes
1190 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1196 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1191 return; 1197 return;
1192 1198
1199 bool overrideNoMod = false;
1200 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1201 overrideNoMod = true;
1202
1193 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1203 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1194 { 1204 {
1195 // object cannot copy items to an object owned by a different owner 1205 // object cannot copy items to an object owned by a different owner
@@ -1199,7 +1209,7 @@ namespace OpenSim.Region.Framework.Scenes
1199 } 1209 }
1200 1210
1201 // must have both move and modify permission to put an item in an object 1211 // must have both move and modify permission to put an item in an object
1202 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1212 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1203 { 1213 {
1204 return; 1214 return;
1205 } 1215 }
@@ -1258,6 +1268,14 @@ namespace OpenSim.Region.Framework.Scenes
1258 1268
1259 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1269 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1260 { 1270 {
1271 SceneObjectPart destPart = GetSceneObjectPart(destID);
1272 if (destPart != null) // Move into a prim
1273 {
1274 foreach(UUID itemID in items)
1275 MoveTaskInventoryItem(destID, host, itemID);
1276 return destID; // Prim folder ID == prim ID
1277 }
1278
1261 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1279 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1262 1280
1263 UUID newFolderID = UUID.Random(); 1281 UUID newFolderID = UUID.Random();
@@ -1437,13 +1455,6 @@ namespace OpenSim.Region.Framework.Scenes
1437 { 1455 {
1438 agentTransactions.HandleTaskItemUpdateFromTransaction( 1456 agentTransactions.HandleTaskItemUpdateFromTransaction(
1439 remoteClient, part, transactionID, currentItem); 1457 remoteClient, part, transactionID, currentItem);
1440
1441 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1442 remoteClient.SendAgentAlertMessage("Notecard saved", false);
1443 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1444 remoteClient.SendAgentAlertMessage("Script saved", false);
1445 else
1446 remoteClient.SendAgentAlertMessage("Item saved", false);
1447 } 1458 }
1448 1459
1449 // Base ALWAYS has move 1460 // Base ALWAYS has move
@@ -1584,7 +1595,7 @@ namespace OpenSim.Region.Framework.Scenes
1584 return; 1595 return;
1585 1596
1586 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1597 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1587 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1598 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1588 remoteClient.AgentId); 1599 remoteClient.AgentId);
1589 AssetService.Store(asset); 1600 AssetService.Store(asset);
1590 1601
@@ -1737,23 +1748,32 @@ namespace OpenSim.Region.Framework.Scenes
1737 // build a list of eligible objects 1748 // build a list of eligible objects
1738 List<uint> deleteIDs = new List<uint>(); 1749 List<uint> deleteIDs = new List<uint>();
1739 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1750 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1740 1751 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1741 // Start with true for both, then remove the flags if objects
1742 // that we can't derez are part of the selection
1743 bool permissionToTake = true;
1744 bool permissionToTakeCopy = true;
1745 bool permissionToDelete = true;
1746 1752
1747 foreach (uint localID in localIDs) 1753 foreach (uint localID in localIDs)
1748 { 1754 {
1755 // Start with true for both, then remove the flags if objects
1756 // that we can't derez are part of the selection
1757 bool permissionToTake = true;
1758 bool permissionToTakeCopy = true;
1759 bool permissionToDelete = true;
1760
1749 // Invalid id 1761 // Invalid id
1750 SceneObjectPart part = GetSceneObjectPart(localID); 1762 SceneObjectPart part = GetSceneObjectPart(localID);
1751 if (part == null) 1763 if (part == null)
1764 {
1765 //Client still thinks the object exists, kill it
1766 deleteIDs.Add(localID);
1752 continue; 1767 continue;
1768 }
1753 1769
1754 // Already deleted by someone else 1770 // Already deleted by someone else
1755 if (part.ParentGroup.IsDeleted) 1771 if (part.ParentGroup.IsDeleted)
1772 {
1773 //Client still thinks the object exists, kill it
1774 deleteIDs.Add(localID);
1756 continue; 1775 continue;
1776 }
1757 1777
1758 // Can't delete child prims 1778 // Can't delete child prims
1759 if (part != part.ParentGroup.RootPart) 1779 if (part != part.ParentGroup.RootPart)
@@ -1761,9 +1781,6 @@ namespace OpenSim.Region.Framework.Scenes
1761 1781
1762 SceneObjectGroup grp = part.ParentGroup; 1782 SceneObjectGroup grp = part.ParentGroup;
1763 1783
1764 deleteIDs.Add(localID);
1765 deleteGroups.Add(grp);
1766
1767 if (remoteClient == null) 1784 if (remoteClient == null)
1768 { 1785 {
1769 // Autoreturn has a null client. Nothing else does. So 1786 // Autoreturn has a null client. Nothing else does. So
@@ -1780,83 +1797,195 @@ namespace OpenSim.Region.Framework.Scenes
1780 } 1797 }
1781 else 1798 else
1782 { 1799 {
1783 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1800 if (action == DeRezAction.TakeCopy)
1801 {
1802 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1803 permissionToTakeCopy = false;
1804 }
1805 else
1806 {
1784 permissionToTakeCopy = false; 1807 permissionToTakeCopy = false;
1785 1808 }
1786 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1809 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1787 permissionToTake = false; 1810 permissionToTake = false;
1788 1811
1789 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1812 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1790 permissionToDelete = false; 1813 permissionToDelete = false;
1791 } 1814 }
1792 }
1793 1815
1794 // Handle god perms 1816 // Handle god perms
1795 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1817 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1796 { 1818 {
1797 permissionToTake = true; 1819 permissionToTake = true;
1798 permissionToTakeCopy = true; 1820 permissionToTakeCopy = true;
1799 permissionToDelete = true; 1821 permissionToDelete = true;
1800 } 1822 }
1801 1823
1802 // If we're re-saving, we don't even want to delete 1824 // If we're re-saving, we don't even want to delete
1803 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1825 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1804 permissionToDelete = false; 1826 permissionToDelete = false;
1805 1827
1806 // if we want to take a copy, we also don't want to delete 1828 // if we want to take a copy, we also don't want to delete
1807 // Note: after this point, the permissionToTakeCopy flag 1829 // Note: after this point, the permissionToTakeCopy flag
1808 // becomes irrelevant. It already includes the permissionToTake 1830 // becomes irrelevant. It already includes the permissionToTake
1809 // permission and after excluding no copy items here, we can 1831 // permission and after excluding no copy items here, we can
1810 // just use that. 1832 // just use that.
1811 if (action == DeRezAction.TakeCopy) 1833 if (action == DeRezAction.TakeCopy)
1812 { 1834 {
1813 // If we don't have permission, stop right here 1835 // If we don't have permission, stop right here
1814 if (!permissionToTakeCopy) 1836 if (!permissionToTakeCopy)
1815 return; 1837 return;
1816 1838
1817 permissionToTake = true; 1839 permissionToTake = true;
1818 // Don't delete 1840 // Don't delete
1819 permissionToDelete = false; 1841 permissionToDelete = false;
1820 } 1842 }
1821 1843
1822 if (action == DeRezAction.Return) 1844 if (action == DeRezAction.Return)
1823 {
1824 if (remoteClient != null)
1825 { 1845 {
1826 if (Permissions.CanReturnObjects( 1846 if (remoteClient != null)
1827 null,
1828 remoteClient.AgentId,
1829 deleteGroups))
1830 { 1847 {
1831 permissionToTake = true; 1848 if (Permissions.CanReturnObjects(
1832 permissionToDelete = true; 1849 null,
1833 1850 remoteClient.AgentId,
1834 foreach (SceneObjectGroup g in deleteGroups) 1851 deleteGroups))
1835 { 1852 {
1836 AddReturn(g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1853 permissionToTake = true;
1854 permissionToDelete = true;
1855
1856 AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1837 } 1857 }
1838 } 1858 }
1859 else // Auto return passes through here with null agent
1860 {
1861 permissionToTake = true;
1862 permissionToDelete = true;
1863 }
1839 } 1864 }
1840 else // Auto return passes through here with null agent 1865
1866 if (permissionToTake && (!permissionToDelete))
1867 takeGroups.Add(grp);
1868
1869 if (permissionToDelete)
1841 { 1870 {
1842 permissionToTake = true; 1871 if (permissionToTake)
1843 permissionToDelete = true; 1872 deleteGroups.Add(grp);
1873 deleteIDs.Add(grp.LocalId);
1844 } 1874 }
1845 } 1875 }
1846 1876
1847 if (permissionToTake) 1877 SendKillObject(deleteIDs);
1878
1879 if (deleteGroups.Count > 0)
1848 { 1880 {
1881 foreach (SceneObjectGroup g in deleteGroups)
1882 deleteIDs.Remove(g.LocalId);
1883
1849 m_asyncSceneObjectDeleter.DeleteToInventory( 1884 m_asyncSceneObjectDeleter.DeleteToInventory(
1850 action, destinationID, deleteGroups, remoteClient, 1885 action, destinationID, deleteGroups, remoteClient,
1851 permissionToDelete); 1886 true);
1887 }
1888 if (takeGroups.Count > 0)
1889 {
1890 m_asyncSceneObjectDeleter.DeleteToInventory(
1891 action, destinationID, takeGroups, remoteClient,
1892 false);
1852 } 1893 }
1853 else if (permissionToDelete) 1894 if (deleteIDs.Count > 0)
1854 { 1895 {
1855 foreach (SceneObjectGroup g in deleteGroups) 1896 foreach (SceneObjectGroup g in deleteGroups)
1856 DeleteSceneObject(g, false); 1897 DeleteSceneObject(g, true);
1857 } 1898 }
1858 } 1899 }
1859 1900
1901 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
1902 {
1903 itemID = UUID.Zero;
1904 if (grp != null)
1905 {
1906 Vector3 inventoryStoredPosition = new Vector3
1907 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
1908 ? 250
1909 : grp.AbsolutePosition.X)
1910 ,
1911 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
1912 ? 250
1913 : grp.AbsolutePosition.X,
1914 grp.AbsolutePosition.Z);
1915
1916 Vector3 originalPosition = grp.AbsolutePosition;
1917
1918 grp.AbsolutePosition = inventoryStoredPosition;
1919
1920 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
1921
1922 grp.AbsolutePosition = originalPosition;
1923
1924 AssetBase asset = CreateAsset(
1925 grp.GetPartName(grp.LocalId),
1926 grp.GetPartDescription(grp.LocalId),
1927 (sbyte)AssetType.Object,
1928 Utils.StringToBytes(sceneObjectXml),
1929 remoteClient.AgentId);
1930 AssetService.Store(asset);
1931
1932 InventoryItemBase item = new InventoryItemBase();
1933 item.CreatorId = grp.RootPart.CreatorID.ToString();
1934 item.CreatorData = grp.RootPart.CreatorData;
1935 item.Owner = remoteClient.AgentId;
1936 item.ID = UUID.Random();
1937 item.AssetID = asset.FullID;
1938 item.Description = asset.Description;
1939 item.Name = asset.Name;
1940 item.AssetType = asset.Type;
1941 item.InvType = (int)InventoryType.Object;
1942
1943 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
1944 if (folder != null)
1945 item.Folder = folder.ID;
1946 else // oopsies
1947 item.Folder = UUID.Zero;
1948
1949 // Set up base perms properly
1950 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
1951 permsBase &= grp.RootPart.BaseMask;
1952 permsBase |= (uint)PermissionMask.Move;
1953
1954 // Make sure we don't lock it
1955 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
1956
1957 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
1958 {
1959 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
1960 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
1961 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1962 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
1963 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
1964 }
1965 else
1966 {
1967 item.BasePermissions = permsBase;
1968 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
1969 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
1970 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
1971 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
1972 }
1973 item.CreationDate = Util.UnixTimeSinceEpoch();
1974
1975 // sets itemID so client can show item as 'attached' in inventory
1976 grp.SetFromItemID(item.ID);
1977
1978 if (AddInventoryItem(item))
1979 remoteClient.SendInventoryItemCreateUpdate(item, 0);
1980 else
1981 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
1982
1983 itemID = item.ID;
1984 return item.AssetID;
1985 }
1986 return UUID.Zero;
1987 }
1988
1860 /// <summary> 1989 /// <summary>
1861 /// Event Handler Rez an object into a scene 1990 /// Event Handler Rez an object into a scene
1862 /// Calls the non-void event handler 1991 /// Calls the non-void event handler
@@ -1983,6 +2112,9 @@ namespace OpenSim.Region.Framework.Scenes
1983 2112
1984 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2113 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
1985 { 2114 {
2115 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2116 return;
2117
1986 SceneObjectPart part = GetSceneObjectPart(objectID); 2118 SceneObjectPart part = GetSceneObjectPart(objectID);
1987 if (part == null) 2119 if (part == null)
1988 return; 2120 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 29d01d6..9da57a8 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -374,7 +374,10 @@ namespace OpenSim.Region.Framework.Scenes
374 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query); 374 List<UserAccount> accounts = UserAccountService.GetUserAccounts(RegionInfo.ScopeID, query);
375 375
376 if (accounts == null) 376 if (accounts == null)
377 {
378 m_log.DebugFormat("[LLCIENT]: ProcessAvatarPickerRequest: returned null result");
377 return; 379 return;
380 }
378 381
379 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); 382 AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket) PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply);
380 // TODO: don't create new blocks if recycling an old packet 383 // TODO: don't create new blocks if recycling an old packet
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
index e1fedf4..48beb9c 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs
@@ -49,6 +49,7 @@ namespace OpenSim.Region.Framework.Scenes
49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition); 49 public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition);
50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene); 50 public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene);
51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene); 51 public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool ViewObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene);
52 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene); 53 public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene);
53 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene); 54 public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene);
54 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene); 55 public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List<SceneObjectGroup> objects, Scene scene);
@@ -116,6 +117,7 @@ namespace OpenSim.Region.Framework.Scenes
116 public event DuplicateObjectHandler OnDuplicateObject; 117 public event DuplicateObjectHandler OnDuplicateObject;
117 public event EditObjectHandler OnEditObject; 118 public event EditObjectHandler OnEditObject;
118 public event EditObjectInventoryHandler OnEditObjectInventory; 119 public event EditObjectInventoryHandler OnEditObjectInventory;
120 public event ViewObjectInventoryHandler OnViewObjectInventory;
119 public event MoveObjectHandler OnMoveObject; 121 public event MoveObjectHandler OnMoveObject;
120 public event ObjectEntryHandler OnObjectEntry; 122 public event ObjectEntryHandler OnObjectEntry;
121 public event ReturnObjectsHandler OnReturnObjects; 123 public event ReturnObjectsHandler OnReturnObjects;
@@ -401,6 +403,21 @@ namespace OpenSim.Region.Framework.Scenes
401 return true; 403 return true;
402 } 404 }
403 405
406 public bool CanViewObjectInventory(UUID objectID, UUID editorID)
407 {
408 ViewObjectInventoryHandler handler = OnViewObjectInventory;
409 if (handler != null)
410 {
411 Delegate[] list = handler.GetInvocationList();
412 foreach (ViewObjectInventoryHandler h in list)
413 {
414 if (h(objectID, editorID, m_scene) == false)
415 return false;
416 }
417 }
418 return true;
419 }
420
404 #endregion 421 #endregion
405 422
406 #region MOVE OBJECT 423 #region MOVE OBJECT
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index d3de37d..26fe61d 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -93,6 +93,7 @@ namespace OpenSim.Region.Framework.Scenes
93 // TODO: need to figure out how allow client agents but deny 93 // TODO: need to figure out how allow client agents but deny
94 // root agents when ACL denies access to root agent 94 // root agents when ACL denies access to root agent
95 public bool m_strictAccessControl = true; 95 public bool m_strictAccessControl = true;
96 public bool m_seeIntoBannedRegion = false;
96 public int MaxUndoCount = 5; 97 public int MaxUndoCount = 5;
97 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 98 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
98 public bool LoginLock = false; 99 public bool LoginLock = false;
@@ -108,12 +109,14 @@ namespace OpenSim.Region.Framework.Scenes
108 109
109 protected int m_splitRegionID; 110 protected int m_splitRegionID;
110 protected Timer m_restartWaitTimer = new Timer(); 111 protected Timer m_restartWaitTimer = new Timer();
112 protected Timer m_timerWatchdog = new Timer();
111 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 113 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
112 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 114 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
113 protected string m_simulatorVersion = "OpenSimulator Server"; 115 protected string m_simulatorVersion = "OpenSimulator Server";
114 protected ModuleLoader m_moduleLoader; 116 protected ModuleLoader m_moduleLoader;
115 protected AgentCircuitManager m_authenticateHandler; 117 protected AgentCircuitManager m_authenticateHandler;
116 protected SceneCommunicationService m_sceneGridService; 118 protected SceneCommunicationService m_sceneGridService;
119 protected ISnmpModule m_snmpService = null;
117 120
118 protected ISimulationDataService m_SimulationDataService; 121 protected ISimulationDataService m_SimulationDataService;
119 protected IEstateDataService m_EstateDataService; 122 protected IEstateDataService m_EstateDataService;
@@ -170,7 +173,7 @@ namespace OpenSim.Region.Framework.Scenes
170 private int m_update_events = 1; 173 private int m_update_events = 1;
171 private int m_update_backup = 200; 174 private int m_update_backup = 200;
172 private int m_update_terrain = 50; 175 private int m_update_terrain = 50;
173// private int m_update_land = 1; 176 private int m_update_land = 10;
174 private int m_update_coarse_locations = 50; 177 private int m_update_coarse_locations = 50;
175 178
176 private int frameMS; 179 private int frameMS;
@@ -184,14 +187,17 @@ namespace OpenSim.Region.Framework.Scenes
184 private int landMS; 187 private int landMS;
185 private int lastCompletedFrame; 188 private int lastCompletedFrame;
186 189
190 public bool CombineRegions = false;
187 private bool m_physics_enabled = true; 191 private bool m_physics_enabled = true;
188 private bool m_scripts_enabled = true; 192 private bool m_scripts_enabled = true;
189 private string m_defaultScriptEngine; 193 private string m_defaultScriptEngine;
190 private int m_LastLogin; 194 private int m_LastLogin;
191 private Thread HeartbeatThread; 195 private Thread HeartbeatThread = null;
192 private volatile bool shuttingdown; 196 private volatile bool shuttingdown;
193 197
194 private int m_lastUpdate; 198 private int m_lastUpdate;
199 private int m_lastIncoming;
200 private int m_lastOutgoing;
195 private bool m_firstHeartbeat = true; 201 private bool m_firstHeartbeat = true;
196 202
197 private object m_deleting_scene_object = new object(); 203 private object m_deleting_scene_object = new object();
@@ -244,6 +250,19 @@ namespace OpenSim.Region.Framework.Scenes
244 get { return m_sceneGridService; } 250 get { return m_sceneGridService; }
245 } 251 }
246 252
253 public ISnmpModule SnmpService
254 {
255 get
256 {
257 if (m_snmpService == null)
258 {
259 m_snmpService = RequestModuleInterface<ISnmpModule>();
260 }
261
262 return m_snmpService;
263 }
264 }
265
247 public ISimulationDataService SimulationDataService 266 public ISimulationDataService SimulationDataService
248 { 267 {
249 get 268 get
@@ -572,7 +591,10 @@ namespace OpenSim.Region.Framework.Scenes
572 m_regInfo = regInfo; 591 m_regInfo = regInfo;
573 m_regionHandle = m_regInfo.RegionHandle; 592 m_regionHandle = m_regInfo.RegionHandle;
574 m_regionName = m_regInfo.RegionName; 593 m_regionName = m_regInfo.RegionName;
594 m_datastore = m_regInfo.DataStore;
575 m_lastUpdate = Util.EnvironmentTickCount(); 595 m_lastUpdate = Util.EnvironmentTickCount();
596 m_lastIncoming = 0;
597 m_lastOutgoing = 0;
576 598
577 m_physicalPrim = physicalPrim; 599 m_physicalPrim = physicalPrim;
578 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor; 600 m_seeIntoRegionFromNeighbor = SeeIntoRegionFromNeighbor;
@@ -588,6 +610,8 @@ namespace OpenSim.Region.Framework.Scenes
588 #region Region Settings 610 #region Region Settings
589 611
590 // Load region settings 612 // Load region settings
613 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID);
614
591 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID); 615 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
592 if (estateDataService != null) 616 if (estateDataService != null)
593 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 617 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@@ -669,9 +693,10 @@ namespace OpenSim.Region.Framework.Scenes
669 //Animation states 693 //Animation states
670 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 694 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
671 // TODO: Change default to true once the feature is supported 695 // TODO: Change default to true once the feature is supported
672 m_usePreJump = startupConfig.GetBoolean("enableprejump", false); 696 m_usePreJump = startupConfig.GetBoolean("enableprejump", true);
673
674 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); 697 m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys);
698
699 m_log.DebugFormat("[SCENE]: prejump is {0}", m_usePreJump ? "ON" : "OFF");
675 if (RegionInfo.NonphysPrimMax > 0) 700 if (RegionInfo.NonphysPrimMax > 0)
676 { 701 {
677 m_maxNonphys = RegionInfo.NonphysPrimMax; 702 m_maxNonphys = RegionInfo.NonphysPrimMax;
@@ -703,6 +728,7 @@ namespace OpenSim.Region.Framework.Scenes
703 m_persistAfter *= 10000000; 728 m_persistAfter *= 10000000;
704 729
705 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 730 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
731 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
706 732
707 IConfig packetConfig = m_config.Configs["PacketPool"]; 733 IConfig packetConfig = m_config.Configs["PacketPool"];
708 if (packetConfig != null) 734 if (packetConfig != null)
@@ -712,6 +738,8 @@ namespace OpenSim.Region.Framework.Scenes
712 } 738 }
713 739
714 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 740 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
741 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
742 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
715 743
716 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 744 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
717 if (m_generateMaptiles) 745 if (m_generateMaptiles)
@@ -736,9 +764,9 @@ namespace OpenSim.Region.Framework.Scenes
736 } 764 }
737 } 765 }
738 } 766 }
739 catch 767 catch (Exception e)
740 { 768 {
741 m_log.Warn("[SCENE]: Failed to load StartupConfig"); 769 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
742 } 770 }
743 771
744 #endregion Region Config 772 #endregion Region Config
@@ -1113,7 +1141,9 @@ namespace OpenSim.Region.Framework.Scenes
1113 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1141 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1114 if (HeartbeatThread != null) 1142 if (HeartbeatThread != null)
1115 { 1143 {
1144 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1116 HeartbeatThread.Abort(); 1145 HeartbeatThread.Abort();
1146 Watchdog.RemoveThread(HeartbeatThread.ManagedThreadId);
1117 HeartbeatThread = null; 1147 HeartbeatThread = null;
1118 } 1148 }
1119 m_lastUpdate = Util.EnvironmentTickCount(); 1149 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1237,9 +1267,6 @@ namespace OpenSim.Region.Framework.Scenes
1237 { 1267 {
1238 while (!shuttingdown) 1268 while (!shuttingdown)
1239 Update(); 1269 Update();
1240
1241 m_lastUpdate = Util.EnvironmentTickCount();
1242 m_firstHeartbeat = false;
1243 } 1270 }
1244 catch (ThreadAbortException) 1271 catch (ThreadAbortException)
1245 { 1272 {
@@ -1345,12 +1372,12 @@ namespace OpenSim.Region.Framework.Scenes
1345 terrainMS = Util.EnvironmentTickCountSubtract(terMS); 1372 terrainMS = Util.EnvironmentTickCountSubtract(terMS);
1346 } 1373 }
1347 1374
1348 //if (Frame % m_update_land == 0) 1375 // if (Frame % m_update_land == 0)
1349 //{ 1376 // {
1350 // int ldMS = Util.EnvironmentTickCount(); 1377 // int ldMS = Util.EnvironmentTickCount();
1351 // UpdateLand(); 1378 // UpdateLand();
1352 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1379 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1353 //} 1380 // }
1354 1381
1355 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS); 1382 frameMS = Util.EnvironmentTickCountSubtract(tmpFrameMS);
1356 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1383 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
@@ -1432,12 +1459,16 @@ namespace OpenSim.Region.Framework.Scenes
1432 maintc = Util.EnvironmentTickCountSubtract(maintc); 1459 maintc = Util.EnvironmentTickCountSubtract(maintc);
1433 maintc = (int)(m_timespan * 1000) - maintc; 1460 maintc = (int)(m_timespan * 1000) - maintc;
1434 1461
1462
1463 m_lastUpdate = Util.EnvironmentTickCount();
1464 m_firstHeartbeat = false;
1465
1435 if (maintc > 0) 1466 if (maintc > 0)
1436 Thread.Sleep(maintc); 1467 Thread.Sleep(maintc);
1437 1468
1438 // Tell the watchdog that this thread is still alive 1469 // Tell the watchdog that this thread is still alive
1439 Watchdog.UpdateThread(); 1470 Watchdog.UpdateThread();
1440 } 1471 }
1441 1472
1442 public void AddGroupTarget(SceneObjectGroup grp) 1473 public void AddGroupTarget(SceneObjectGroup grp)
1443 { 1474 {
@@ -1453,9 +1484,9 @@ namespace OpenSim.Region.Framework.Scenes
1453 1484
1454 private void CheckAtTargets() 1485 private void CheckAtTargets()
1455 { 1486 {
1456 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1487 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1457 lock (m_groupsWithTargets) 1488 lock (m_groupsWithTargets)
1458 objs = m_groupsWithTargets.Values; 1489 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1459 1490
1460 foreach (SceneObjectGroup entry in objs) 1491 foreach (SceneObjectGroup entry in objs)
1461 entry.checkAtTargets(); 1492 entry.checkAtTargets();
@@ -1773,14 +1804,24 @@ namespace OpenSim.Region.Framework.Scenes
1773 /// <returns></returns> 1804 /// <returns></returns>
1774 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1805 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1775 { 1806 {
1807
1808 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1809 Vector3 wpos = Vector3.Zero;
1810 // Check for water surface intersection from above
1811 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1812 {
1813 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1814 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1815 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1816 wpos.Z = wheight;
1817 }
1818
1776 Vector3 pos = Vector3.Zero; 1819 Vector3 pos = Vector3.Zero;
1777 if (RayEndIsIntersection == (byte)1) 1820 if (RayEndIsIntersection == (byte)1)
1778 { 1821 {
1779 pos = RayEnd; 1822 pos = RayEnd;
1780 return pos;
1781 } 1823 }
1782 1824 else if (RayTargetID != UUID.Zero)
1783 if (RayTargetID != UUID.Zero)
1784 { 1825 {
1785 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1826 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1786 1827
@@ -1802,7 +1843,7 @@ namespace OpenSim.Region.Framework.Scenes
1802 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1843 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1803 1844
1804 // Un-comment out the following line to Get Raytrace results printed to the console. 1845 // 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()); 1846 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1806 float ScaleOffset = 0.5f; 1847 float ScaleOffset = 0.5f;
1807 1848
1808 // If we hit something 1849 // If we hit something
@@ -1825,13 +1866,10 @@ namespace OpenSim.Region.Framework.Scenes
1825 //pos.Z -= 0.25F; 1866 //pos.Z -= 0.25F;
1826 1867
1827 } 1868 }
1828
1829 return pos;
1830 } 1869 }
1831 else 1870 else
1832 { 1871 {
1833 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1872 // 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); 1873 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1836 1874
1837 // Un-comment the following line to print the raytrace results to the console. 1875 // Un-comment the following line to print the raytrace results to the console.
@@ -1840,13 +1878,12 @@ namespace OpenSim.Region.Framework.Scenes
1840 if (ei.HitTF) 1878 if (ei.HitTF)
1841 { 1879 {
1842 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1880 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1843 } else 1881 }
1882 else
1844 { 1883 {
1845 // fall back to our stupid functionality 1884 // fall back to our stupid functionality
1846 pos = RayEnd; 1885 pos = RayEnd;
1847 } 1886 }
1848
1849 return pos;
1850 } 1887 }
1851 } 1888 }
1852 else 1889 else
@@ -1857,8 +1894,12 @@ namespace OpenSim.Region.Framework.Scenes
1857 //increase height so its above the ground. 1894 //increase height so its above the ground.
1858 //should be getting the normal of the ground at the rez point and using that? 1895 //should be getting the normal of the ground at the rez point and using that?
1859 pos.Z += scale.Z / 2f; 1896 pos.Z += scale.Z / 2f;
1860 return pos; 1897// return pos;
1861 } 1898 }
1899
1900 // check against posible water intercept
1901 if (wpos.Z > pos.Z) pos = wpos;
1902 return pos;
1862 } 1903 }
1863 1904
1864 1905
@@ -1942,7 +1983,10 @@ namespace OpenSim.Region.Framework.Scenes
1942 public bool AddRestoredSceneObject( 1983 public bool AddRestoredSceneObject(
1943 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1984 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1944 { 1985 {
1945 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 1986 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
1987 if (result)
1988 sceneObject.IsDeleted = false;
1989 return result;
1946 } 1990 }
1947 1991
1948 /// <summary> 1992 /// <summary>
@@ -2032,6 +2076,15 @@ namespace OpenSim.Region.Framework.Scenes
2032 /// </summary> 2076 /// </summary>
2033 public void DeleteAllSceneObjects() 2077 public void DeleteAllSceneObjects()
2034 { 2078 {
2079 DeleteAllSceneObjects(false);
2080 }
2081
2082 /// <summary>
2083 /// Delete every object from the scene. This does not include attachments worn by avatars.
2084 /// </summary>
2085 public void DeleteAllSceneObjects(bool exceptNoCopy)
2086 {
2087 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2035 lock (Entities) 2088 lock (Entities)
2036 { 2089 {
2037 EntityBase[] entities = Entities.GetEntities(); 2090 EntityBase[] entities = Entities.GetEntities();
@@ -2040,11 +2093,24 @@ namespace OpenSim.Region.Framework.Scenes
2040 if (e is SceneObjectGroup) 2093 if (e is SceneObjectGroup)
2041 { 2094 {
2042 SceneObjectGroup sog = (SceneObjectGroup)e; 2095 SceneObjectGroup sog = (SceneObjectGroup)e;
2043 if (!sog.IsAttachment) 2096 if (sog != null && !sog.IsAttachment)
2044 DeleteSceneObject((SceneObjectGroup)e, false); 2097 {
2098 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2099 {
2100 DeleteSceneObject((SceneObjectGroup)e, false);
2101 }
2102 else
2103 {
2104 toReturn.Add((SceneObjectGroup)e);
2105 }
2106 }
2045 } 2107 }
2046 } 2108 }
2047 } 2109 }
2110 if (toReturn.Count > 0)
2111 {
2112 returnObjects(toReturn.ToArray(), UUID.Zero);
2113 }
2048 } 2114 }
2049 2115
2050 /// <summary> 2116 /// <summary>
@@ -2093,6 +2159,8 @@ namespace OpenSim.Region.Framework.Scenes
2093 } 2159 }
2094 2160
2095 group.DeleteGroupFromScene(silent); 2161 group.DeleteGroupFromScene(silent);
2162 if (!silent)
2163 SendKillObject(new List<uint>() { group.LocalId });
2096 2164
2097// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2165// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2098 } 2166 }
@@ -2445,10 +2513,17 @@ namespace OpenSim.Region.Framework.Scenes
2445 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2513 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2446 public bool AddSceneObject(SceneObjectGroup sceneObject) 2514 public bool AddSceneObject(SceneObjectGroup sceneObject)
2447 { 2515 {
2516 if (sceneObject.OwnerID == UUID.Zero)
2517 {
2518 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2519 return false;
2520 }
2521
2448 // If the user is banned, we won't let any of their objects 2522 // If the user is banned, we won't let any of their objects
2449 // enter. Period. 2523 // enter. Period.
2450 // 2524 //
2451 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2525 int flags = GetUserFlags(sceneObject.OwnerID);
2526 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2452 { 2527 {
2453 m_log.Info("[INTERREGION]: Denied prim crossing for " + 2528 m_log.Info("[INTERREGION]: Denied prim crossing for " +
2454 "banned avatar"); 2529 "banned avatar");
@@ -2492,15 +2567,28 @@ namespace OpenSim.Region.Framework.Scenes
2492 2567
2493 if (AttachmentsModule != null) 2568 if (AttachmentsModule != null)
2494 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); 2569 AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false);
2570
2571 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was found, attaching", sceneObject.UUID);
2495 } 2572 }
2496 else 2573 else
2497 { 2574 {
2575 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2498 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2576 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2499 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2577 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2500 } 2578 }
2579 if (sceneObject.OwnerID == UUID.Zero)
2580 {
2581 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2582 return false;
2583 }
2501 } 2584 }
2502 else 2585 else
2503 { 2586 {
2587 if (sceneObject.OwnerID == UUID.Zero)
2588 {
2589 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2590 return false;
2591 }
2504 AddRestoredSceneObject(sceneObject, true, false); 2592 AddRestoredSceneObject(sceneObject, true, false);
2505 2593
2506 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2594 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2530,6 +2618,24 @@ namespace OpenSim.Region.Framework.Scenes
2530 return 2; // StateSource.PrimCrossing 2618 return 2; // StateSource.PrimCrossing
2531 } 2619 }
2532 2620
2621 public int GetUserFlags(UUID user)
2622 {
2623 //Unfortunately the SP approach means that the value is cached until region is restarted
2624 /*
2625 ScenePresence sp;
2626 if (TryGetScenePresence(user, out sp))
2627 {
2628 return sp.UserFlags;
2629 }
2630 else
2631 {
2632 */
2633 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2634 if (uac == null)
2635 return 0;
2636 return uac.UserFlags;
2637 //}
2638 }
2533 #endregion 2639 #endregion
2534 2640
2535 #region Add/Remove Avatar Methods 2641 #region Add/Remove Avatar Methods
@@ -2551,6 +2657,7 @@ namespace OpenSim.Region.Framework.Scenes
2551 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2657 (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2552 2658
2553 CheckHeartbeat(); 2659 CheckHeartbeat();
2660 ScenePresence presence;
2554 2661
2555 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here 2662 if (GetScenePresence(client.AgentId) == null) // ensure there is no SP here
2556 { 2663 {
@@ -2584,7 +2691,14 @@ namespace OpenSim.Region.Framework.Scenes
2584 2691
2585 EventManager.TriggerOnNewClient(client); 2692 EventManager.TriggerOnNewClient(client);
2586 if (vialogin) 2693 if (vialogin)
2694 {
2587 EventManager.TriggerOnClientLogin(client); 2695 EventManager.TriggerOnClientLogin(client);
2696
2697 // Send initial parcel data
2698 Vector3 pos = presence.AbsolutePosition;
2699 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2700 land.SendLandUpdateToClient(presence.ControllingClient);
2701 }
2588 } 2702 }
2589 } 2703 }
2590 2704
@@ -2673,19 +2787,12 @@ namespace OpenSim.Region.Framework.Scenes
2673 // and the scene presence and the client, if they exist 2787 // and the scene presence and the client, if they exist
2674 try 2788 try
2675 { 2789 {
2676 // We need to wait for the client to make UDP contact first. 2790 ScenePresence sp = GetScenePresence(agentID);
2677 // It's the UDP contact that creates the scene presence 2791 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2678 ScenePresence sp = WaitGetScenePresence(agentID); 2792
2679 if (sp != null) 2793 if (sp != null)
2680 {
2681 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2682
2683 sp.ControllingClient.Close(); 2794 sp.ControllingClient.Close();
2684 } 2795
2685 else
2686 {
2687 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2688 }
2689 // BANG! SLASH! 2796 // BANG! SLASH!
2690 m_authenticateHandler.RemoveCircuit(agentID); 2797 m_authenticateHandler.RemoveCircuit(agentID);
2691 2798
@@ -2785,6 +2892,7 @@ namespace OpenSim.Region.Framework.Scenes
2785 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2892 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2786 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2893 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2787 client.OnCopyInventoryItem += CopyInventoryItem; 2894 client.OnCopyInventoryItem += CopyInventoryItem;
2895 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2788 client.OnMoveInventoryItem += MoveInventoryItem; 2896 client.OnMoveInventoryItem += MoveInventoryItem;
2789 client.OnRemoveInventoryItem += RemoveInventoryItem; 2897 client.OnRemoveInventoryItem += RemoveInventoryItem;
2790 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2898 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2962,15 +3070,16 @@ namespace OpenSim.Region.Framework.Scenes
2962 /// </summary> 3070 /// </summary>
2963 /// <param name="agentId">The avatar's Unique ID</param> 3071 /// <param name="agentId">The avatar's Unique ID</param>
2964 /// <param name="client">The IClientAPI for the client</param> 3072 /// <param name="client">The IClientAPI for the client</param>
2965 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3073 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2966 { 3074 {
2967 if (m_teleportModule != null) 3075 if (m_teleportModule != null)
2968 m_teleportModule.TeleportHome(agentId, client); 3076 return m_teleportModule.TeleportHome(agentId, client);
2969 else 3077 else
2970 { 3078 {
2971 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3079 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2972 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3080 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2973 } 3081 }
3082 return false;
2974 } 3083 }
2975 3084
2976 /// <summary> 3085 /// <summary>
@@ -3062,6 +3171,16 @@ namespace OpenSim.Region.Framework.Scenes
3062 /// <param name="flags"></param> 3171 /// <param name="flags"></param>
3063 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3172 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3064 { 3173 {
3174 //Add half the avatar's height so that the user doesn't fall through prims
3175 ScenePresence presence;
3176 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3177 {
3178 if (presence.Appearance != null)
3179 {
3180 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3181 }
3182 }
3183
3065 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3184 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3066 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3185 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3067 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3186 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3136,8 +3255,9 @@ namespace OpenSim.Region.Framework.Scenes
3136 regions.Remove(RegionInfo.RegionHandle); 3255 regions.Remove(RegionInfo.RegionHandle);
3137 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3256 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3138 } 3257 }
3139 3258 m_log.Debug("[Scene] Beginning ClientClosed");
3140 m_eventManager.TriggerClientClosed(agentID, this); 3259 m_eventManager.TriggerClientClosed(agentID, this);
3260 m_log.Debug("[Scene] Finished ClientClosed");
3141 } 3261 }
3142 catch (NullReferenceException) 3262 catch (NullReferenceException)
3143 { 3263 {
@@ -3145,16 +3265,21 @@ namespace OpenSim.Region.Framework.Scenes
3145 // Avatar is already disposed :/ 3265 // Avatar is already disposed :/
3146 } 3266 }
3147 3267
3268 m_log.Debug("[Scene] Beginning OnRemovePresence");
3148 m_eventManager.TriggerOnRemovePresence(agentID); 3269 m_eventManager.TriggerOnRemovePresence(agentID);
3270 m_log.Debug("[Scene] Finished OnRemovePresence");
3149 3271
3150 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc) 3272 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
3151 AttachmentsModule.SaveChangedAttachments(avatar); 3273 AttachmentsModule.SaveChangedAttachments(avatar);
3152 3274
3275 if (avatar != null && (!avatar.IsChildAgent))
3276 avatar.SaveChangedAttachments();
3277
3153 ForEachClient( 3278 ForEachClient(
3154 delegate(IClientAPI client) 3279 delegate(IClientAPI client)
3155 { 3280 {
3156 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway 3281 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3157 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); } 3282 try { client.SendKillObject(avatar.RegionHandle, new List<uint>() { avatar.LocalId}); }
3158 catch (NullReferenceException) { } 3283 catch (NullReferenceException) { }
3159 }); 3284 });
3160 3285
@@ -3165,8 +3290,11 @@ namespace OpenSim.Region.Framework.Scenes
3165 } 3290 }
3166 3291
3167 // Remove the avatar from the scene 3292 // Remove the avatar from the scene
3293 m_log.Debug("[Scene] Begin RemoveScenePresence");
3168 m_sceneGraph.RemoveScenePresence(agentID); 3294 m_sceneGraph.RemoveScenePresence(agentID);
3295 m_log.Debug("[Scene] Finished RemoveScenePresence. Removing the client manager");
3169 m_clientManager.Remove(agentID); 3296 m_clientManager.Remove(agentID);
3297 m_log.Debug("[Scene] Removed the client manager. Firing avatar.close");
3170 3298
3171 try 3299 try
3172 { 3300 {
@@ -3180,9 +3308,10 @@ namespace OpenSim.Region.Framework.Scenes
3180 { 3308 {
3181 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString()); 3309 m_log.Error("[SCENE] Scene.cs:RemoveClient exception: " + e.ToString());
3182 } 3310 }
3183 3311 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3184 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3312 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3185// CleanDroppedAttachments(); 3313// CleanDroppedAttachments();
3314 m_log.Debug("[Scene] The avatar has left the building");
3186 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3315 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3187 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3316 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3188 } 3317 }
@@ -3213,19 +3342,24 @@ namespace OpenSim.Region.Framework.Scenes
3213 3342
3214 #region Entities 3343 #region Entities
3215 3344
3216 public void SendKillObject(uint localID) 3345 public void SendKillObject(List<uint> localIDs)
3217 { 3346 {
3218 SceneObjectPart part = GetSceneObjectPart(localID); 3347 List<uint> deleteIDs = new List<uint>();
3219 if (part != null) // It is a prim 3348
3349 foreach (uint localID in localIDs)
3220 { 3350 {
3221 if (!part.ParentGroup.IsDeleted) // Valid 3351 SceneObjectPart part = GetSceneObjectPart(localID);
3352 if (part != null) // It is a prim
3222 { 3353 {
3223 if (part.ParentGroup.RootPart != part) // Child part 3354 if (part.ParentGroup != null && !part.ParentGroup.IsDeleted) // Valid
3224 return; 3355 {
3356 if (part.ParentGroup.RootPart != part) // Child part
3357 continue;
3358 }
3225 } 3359 }
3360 deleteIDs.Add(localID);
3226 } 3361 }
3227 3362 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, deleteIDs); });
3228 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); });
3229 } 3363 }
3230 3364
3231 #endregion 3365 #endregion
@@ -3243,7 +3377,6 @@ namespace OpenSim.Region.Framework.Scenes
3243 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate; 3377 //m_sceneGridService.OnChildAgentUpdate += IncomingChildAgentDataUpdate;
3244 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar; 3378 //m_sceneGridService.OnRemoveKnownRegionFromAvatar += HandleRemoveKnownRegionsFromAvatar;
3245 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid; 3379 m_sceneGridService.OnLogOffUser += HandleLogOffUserFromGrid;
3246 m_sceneGridService.KiPrimitive += SendKillObject;
3247 m_sceneGridService.OnGetLandData += GetLandData; 3380 m_sceneGridService.OnGetLandData += GetLandData;
3248 } 3381 }
3249 3382
@@ -3252,7 +3385,6 @@ namespace OpenSim.Region.Framework.Scenes
3252 /// </summary> 3385 /// </summary>
3253 public void UnRegisterRegionWithComms() 3386 public void UnRegisterRegionWithComms()
3254 { 3387 {
3255 m_sceneGridService.KiPrimitive -= SendKillObject;
3256 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid; 3388 m_sceneGridService.OnLogOffUser -= HandleLogOffUserFromGrid;
3257 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar; 3389 //m_sceneGridService.OnRemoveKnownRegionFromAvatar -= HandleRemoveKnownRegionsFromAvatar;
3258 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate; 3390 //m_sceneGridService.OnChildAgentUpdate -= IncomingChildAgentDataUpdate;
@@ -3332,13 +3464,16 @@ namespace OpenSim.Region.Framework.Scenes
3332 sp = null; 3464 sp = null;
3333 } 3465 }
3334 3466
3335 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3336 3467
3337 //On login test land permisions 3468 //On login test land permisions
3338 if (vialogin) 3469 if (vialogin)
3339 { 3470 {
3340 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3471 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3472 if (cache != null)
3473 cache.Remove(agent.firstname + " " + agent.lastname);
3474 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3341 { 3475 {
3476 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3342 return false; 3477 return false;
3343 } 3478 }
3344 } 3479 }
@@ -3361,8 +3496,13 @@ namespace OpenSim.Region.Framework.Scenes
3361 3496
3362 try 3497 try
3363 { 3498 {
3364 if (!AuthorizeUser(agent, out reason)) 3499 // Always check estate if this is a login. Always
3365 return false; 3500 // check if banned regions are to be blacked out.
3501 if (vialogin || (!m_seeIntoBannedRegion))
3502 {
3503 if (!AuthorizeUser(agent.AgentID, out reason))
3504 return false;
3505 }
3366 } 3506 }
3367 catch (Exception e) 3507 catch (Exception e)
3368 { 3508 {
@@ -3464,6 +3604,8 @@ namespace OpenSim.Region.Framework.Scenes
3464 } 3604 }
3465 } 3605 }
3466 // Honor parcel landing type and position. 3606 // Honor parcel landing type and position.
3607 /*
3608 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3467 if (land != null) 3609 if (land != null)
3468 { 3610 {
3469 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3611 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3471,26 +3613,34 @@ namespace OpenSim.Region.Framework.Scenes
3471 agent.startpos = land.LandData.UserLocation; 3613 agent.startpos = land.LandData.UserLocation;
3472 } 3614 }
3473 } 3615 }
3616 */// This is now handled properly in ScenePresence.MakeRootAgent
3474 } 3617 }
3475 3618
3476 return true; 3619 return true;
3477 } 3620 }
3478 3621
3479 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3622 private bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3480 { 3623 {
3481 3624 reason = String.Empty;
3482 bool banned = land.IsBannedFromLand(agent.AgentID); 3625 if (Permissions.IsGod(agentID))
3483 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3626 return true;
3627
3628 ILandObject land = LandChannel.GetLandObject(posX, posY);
3629 if (land == null)
3630 return false;
3631
3632 bool banned = land.IsBannedFromLand(agentID);
3633 bool restricted = land.IsRestrictedFromLand(agentID);
3484 3634
3485 if (banned || restricted) 3635 if (banned || restricted)
3486 { 3636 {
3487 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3637 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3488 if (nearestParcel != null) 3638 if (nearestParcel != null)
3489 { 3639 {
3490 //Move agent to nearest allowed 3640 //Move agent to nearest allowed
3491 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3641 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3492 agent.startpos.X = newPosition.X; 3642 posX = newPosition.X;
3493 agent.startpos.Y = newPosition.Y; 3643 posY = newPosition.Y;
3494 } 3644 }
3495 else 3645 else
3496 { 3646 {
@@ -3546,20 +3696,20 @@ namespace OpenSim.Region.Framework.Scenes
3546 /// <param name="reason">outputs the reason to this string</param> 3696 /// <param name="reason">outputs the reason to this string</param>
3547 /// <returns>True if the region accepts this agent. False if it does not. False will 3697 /// <returns>True if the region accepts this agent. False if it does not. False will
3548 /// also return a reason.</returns> 3698 /// also return a reason.</returns>
3549 protected virtual bool AuthorizeUser(AgentCircuitData agent, out string reason) 3699 protected virtual bool AuthorizeUser(UUID agentID, out string reason)
3550 { 3700 {
3551 reason = String.Empty; 3701 reason = String.Empty;
3552 3702
3553 if (!m_strictAccessControl) return true; 3703 if (!m_strictAccessControl) return true;
3554 if (Permissions.IsGod(agent.AgentID)) return true; 3704 if (Permissions.IsGod(agentID)) return true;
3555 3705
3556 if (AuthorizationService != null) 3706 if (AuthorizationService != null)
3557 { 3707 {
3558 if (!AuthorizationService.IsAuthorizedForRegion( 3708 if (!AuthorizationService.IsAuthorizedForRegion(
3559 agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason)) 3709 agent.AgentID.ToString(), agent.firstname, agent.lastname, RegionInfo.RegionID.ToString(), out reason))
3560 { 3710 {
3561 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", 3711 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the region",
3562 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3712 agentID, RegionInfo.RegionName);
3563 3713
3564 return false; 3714 return false;
3565 } 3715 }
@@ -3567,10 +3717,26 @@ namespace OpenSim.Region.Framework.Scenes
3567 3717
3568 if (m_regInfo.EstateSettings != null) 3718 if (m_regInfo.EstateSettings != null)
3569 { 3719 {
3570 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3720 int flags = GetUserFlags(agentID);
3721 if (m_regInfo.EstateSettings.IsBanned(agentID, flags))
3571 { 3722 {
3572 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3723 //Add some more info to help users
3573 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3724 if (!m_regInfo.EstateSettings.IsBanned(agentID, 32))
3725 {
3726 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the region requires age verification",
3727 agentID, RegionInfo.RegionName);
3728 reason = String.Format("Denied access to region {0}: Region requires age verification", RegionInfo.RegionName);
3729 return false;
3730 }
3731 if (!m_regInfo.EstateSettings.IsBanned(agentID, 4))
3732 {
3733 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} {1} because the region requires payment info on file",
3734 agentID, RegionInfo.RegionName);
3735 reason = String.Format("Denied access to region {0}: Region requires payment info on file", RegionInfo.RegionName);
3736 return false;
3737 }
3738 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {3} because the user is on the banlist",
3739 agentID, RegionInfo.RegionName);
3574 reason = String.Format("Denied access to region {0}: You have been banned from that region.", 3740 reason = String.Format("Denied access to region {0}: You have been banned from that region.",
3575 RegionInfo.RegionName); 3741 RegionInfo.RegionName);
3576 return false; 3742 return false;
@@ -3587,7 +3753,7 @@ namespace OpenSim.Region.Framework.Scenes
3587 if (groupsModule != null) 3753 if (groupsModule != null)
3588 { 3754 {
3589 GroupMembershipData[] GroupMembership = 3755 GroupMembershipData[] GroupMembership =
3590 groupsModule.GetMembershipData(agent.AgentID); 3756 groupsModule.GetMembershipData(agentID);
3591 3757
3592 if (GroupMembership != null) 3758 if (GroupMembership != null)
3593 { 3759 {
@@ -3616,44 +3782,16 @@ namespace OpenSim.Region.Framework.Scenes
3616 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); 3782 m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!");
3617 3783
3618 if (!m_regInfo.EstateSettings.PublicAccess && 3784 if (!m_regInfo.EstateSettings.PublicAccess &&
3619 !m_regInfo.EstateSettings.HasAccess(agent.AgentID) && 3785 !m_regInfo.EstateSettings.HasAccess(agentID) &&
3620 !groupAccess) 3786 !groupAccess)
3621 { 3787 {
3622 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", 3788 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} at {1} because the user does not have access to the estate",
3623 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3789 agentID, RegionInfo.RegionName);
3624 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", 3790 reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3625 RegionInfo.RegionName); 3791 RegionInfo.RegionName);
3626 return false; 3792 return false;
3627 } 3793 }
3628 3794
3629 // TODO: estate/region settings are not properly hooked up
3630 // to ILandObject.isRestrictedFromLand()
3631 // if (null != LandChannel)
3632 // {
3633 // // region seems to have local Id of 1
3634 // ILandObject land = LandChannel.GetLandObject(1);
3635 // if (null != land)
3636 // {
3637 // if (land.isBannedFromLand(agent.AgentID))
3638 // {
3639 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land",
3640 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3641 // reason = String.Format("Denied access to private region {0}: You are banned from that region.",
3642 // RegionInfo.RegionName);
3643 // return false;
3644 // }
3645
3646 // if (land.isRestrictedFromLand(agent.AgentID))
3647 // {
3648 // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region",
3649 // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
3650 // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.",
3651 // RegionInfo.RegionName);
3652 // return false;
3653 // }
3654 // }
3655 // }
3656
3657 return true; 3795 return true;
3658 } 3796 }
3659 3797
@@ -3757,6 +3895,13 @@ namespace OpenSim.Region.Framework.Scenes
3757 3895
3758 // We have to wait until the viewer contacts this region after receiving EAC. 3896 // We have to wait until the viewer contacts this region after receiving EAC.
3759 // That calls AddNewClient, which finally creates the ScenePresence 3897 // That calls AddNewClient, which finally creates the ScenePresence
3898 int flags = GetUserFlags(cAgentData.AgentID);
3899 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3900 {
3901 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3902 return false;
3903 }
3904
3760 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3905 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3761 if (nearestParcel == null) 3906 if (nearestParcel == null)
3762 { 3907 {
@@ -3772,7 +3917,6 @@ namespace OpenSim.Region.Framework.Scenes
3772 return false; 3917 return false;
3773 } 3918 }
3774 3919
3775
3776 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); 3920 ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID);
3777 3921
3778 if (childAgentUpdate != null) 3922 if (childAgentUpdate != null)
@@ -3839,12 +3983,22 @@ namespace OpenSim.Region.Framework.Scenes
3839 return false; 3983 return false;
3840 } 3984 }
3841 3985
3986 public bool IncomingCloseAgent(UUID agentID)
3987 {
3988 return IncomingCloseAgent(agentID, false);
3989 }
3990
3991 public bool IncomingCloseChildAgent(UUID agentID)
3992 {
3993 return IncomingCloseAgent(agentID, true);
3994 }
3995
3842 /// <summary> 3996 /// <summary>
3843 /// Tell a single agent to disconnect from the region. 3997 /// Tell a single agent to disconnect from the region.
3844 /// </summary> 3998 /// </summary>
3845 /// <param name="regionHandle"></param>
3846 /// <param name="agentID"></param> 3999 /// <param name="agentID"></param>
3847 public bool IncomingCloseAgent(UUID agentID) 4000 /// <param name="childOnly"></param>
4001 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3848 { 4002 {
3849 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4003 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3850 4004
@@ -3856,7 +4010,7 @@ namespace OpenSim.Region.Framework.Scenes
3856 { 4010 {
3857 m_sceneGraph.removeUserCount(false); 4011 m_sceneGraph.removeUserCount(false);
3858 } 4012 }
3859 else 4013 else if (!childOnly)
3860 { 4014 {
3861 m_sceneGraph.removeUserCount(true); 4015 m_sceneGraph.removeUserCount(true);
3862 } 4016 }
@@ -3872,9 +4026,12 @@ namespace OpenSim.Region.Framework.Scenes
3872 } 4026 }
3873 else 4027 else
3874 presence.ControllingClient.SendShutdownConnectionNotice(); 4028 presence.ControllingClient.SendShutdownConnectionNotice();
4029 presence.ControllingClient.Close(false);
4030 }
4031 else if (!childOnly)
4032 {
4033 presence.ControllingClient.Close(true);
3875 } 4034 }
3876
3877 presence.ControllingClient.Close();
3878 return true; 4035 return true;
3879 } 4036 }
3880 4037
@@ -4489,34 +4646,66 @@ namespace OpenSim.Region.Framework.Scenes
4489 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4646 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4490 } 4647 }
4491 4648
4492 public int GetHealth() 4649 public int GetHealth(out int flags, out string message)
4493 { 4650 {
4494 // Returns: 4651 // Returns:
4495 // 1 = sim is up and accepting http requests. The heartbeat has 4652 // 1 = sim is up and accepting http requests. The heartbeat has
4496 // stopped and the sim is probably locked up, but a remote 4653 // stopped and the sim is probably locked up, but a remote
4497 // admin restart may succeed 4654 // admin restart may succeed
4498 // 4655 //
4499 // 2 = Sim is up and the heartbeat is running. The sim is likely 4656 // 2 = Sim is up and the heartbeat is running. The sim is likely
4500 // usable for people within and logins _may_ work 4657 // usable for people within
4658 //
4659 // 3 = Sim is up and one packet thread is running. Sim is
4660 // unstable and will not accept new logins
4661 //
4662 // 4 = Sim is up and both packet threads are running. Sim is
4663 // likely usable
4501 // 4664 //
4502 // 3 = We have seen a new user enter within the past 4 minutes 4665 // 5 = We have seen a new user enter within the past 4 minutes
4503 // which can be seen as positive confirmation of sim health 4666 // which can be seen as positive confirmation of sim health
4504 // 4667 //
4668
4669 flags = 0;
4670 message = String.Empty;
4671
4672 CheckHeartbeat();
4673
4674 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4675 {
4676 // We're still starting
4677 // 0 means "in startup", it can't happen another way, since
4678 // to get here, we must be able to accept http connections
4679 return 0;
4680 }
4681
4505 int health=1; // Start at 1, means we're up 4682 int health=1; // Start at 1, means we're up
4506 4683
4507 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4684 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4685 {
4508 health+=1; 4686 health+=1;
4509 else 4687 flags |= 1;
4688 }
4689
4690 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4691 {
4692 health+=1;
4693 flags |= 2;
4694 }
4695
4696 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4697 {
4698 health+=1;
4699 flags |= 4;
4700 }
4701
4702 if (flags != 7)
4510 return health; 4703 return health;
4511 4704
4512 // A login in the last 4 mins? We can't be doing too badly 4705 // A login in the last 4 mins? We can't be doing too badly
4513 // 4706 //
4514 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4707 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4515 health++; 4708 health++;
4516 else
4517 return health;
4518
4519 CheckHeartbeat();
4520 4709
4521 return health; 4710 return health;
4522 } 4711 }
@@ -4709,7 +4898,7 @@ namespace OpenSim.Region.Framework.Scenes
4709 if (m_firstHeartbeat) 4898 if (m_firstHeartbeat)
4710 return; 4899 return;
4711 4900
4712 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4901 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4713 StartTimer(); 4902 StartTimer();
4714 } 4903 }
4715 4904
@@ -5158,6 +5347,54 @@ namespace OpenSim.Region.Framework.Scenes
5158// } 5347// }
5159// } 5348// }
5160 5349
5350 lock (m_cleaningAttachments)
5351 {
5352 ForEachSOG(delegate (SceneObjectGroup grp)
5353 {
5354 if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5355 {
5356 UUID agentID = grp.OwnerID;
5357 if (agentID == UUID.Zero)
5358 {
5359 objectsToDelete.Add(grp);
5360 return;
5361 }
5362
5363 ScenePresence sp = GetScenePresence(agentID);
5364 if (sp == null)
5365 {
5366 objectsToDelete.Add(grp);
5367 return;
5368 }
5369 }
5370 });
5371 }
5372
5373 if (objectsToDelete.Count > 0)
5374 {
5375 m_log.DebugFormat("[SCENE]: Starting delete of {0} dropped attachments", objectsToDelete.Count);
5376 foreach (SceneObjectGroup grp in objectsToDelete)
5377 {
5378 m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5379 DeleteSceneObject(grp, true);
5380 }
5381 m_log.Debug("[SCENE]: Finished dropped attachment deletion");
5382 }
5383 }
5384
5385 public void ThreadAlive(int threadCode)
5386 {
5387 switch(threadCode)
5388 {
5389 case 1: // Incoming
5390 m_lastIncoming = Util.EnvironmentTickCount();
5391 break;
5392 case 2: // Incoming
5393 m_lastOutgoing = Util.EnvironmentTickCount();
5394 break;
5395 }
5396 }
5397
5161 // This method is called across the simulation connector to 5398 // This method is called across the simulation connector to
5162 // determine if a given agent is allowed in this region 5399 // determine if a given agent is allowed in this region
5163 // AS A ROOT AGENT. Returning false here will prevent them 5400 // AS A ROOT AGENT. Returning false here will prevent them
@@ -5166,6 +5403,14 @@ namespace OpenSim.Region.Framework.Scenes
5166 // child agent creation, thereby emulating the SL behavior. 5403 // child agent creation, thereby emulating the SL behavior.
5167 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5404 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5168 { 5405 {
5406 reason = "You are banned from the region";
5407
5408 if (Permissions.IsGod(agentID))
5409 {
5410 reason = String.Empty;
5411 return true;
5412 }
5413
5169 int num = m_sceneGraph.GetNumberOfScenePresences(); 5414 int num = m_sceneGraph.GetNumberOfScenePresences();
5170 5415
5171 if (num >= RegionInfo.RegionSettings.AgentLimit) 5416 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5177,8 +5422,51 @@ namespace OpenSim.Region.Framework.Scenes
5177 } 5422 }
5178 } 5423 }
5179 5424
5425 if (!AuthorizeUser(agentID, out reason))
5426 {
5427 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5428 return false;
5429 }
5430
5431 if (position == Vector3.Zero) // Teleport
5432 {
5433 float posX = 128.0f;
5434 float posY = 128.0f;
5435
5436 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5437 {
5438 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5439 return false;
5440 }
5441 }
5442 else // Walking
5443 {
5444 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5445 if (land == null)
5446 return false;
5447
5448 bool banned = land.IsBannedFromLand(agentID);
5449 bool restricted = land.IsRestrictedFromLand(agentID);
5450
5451 if (banned || restricted)
5452 return false;
5453 }
5454
5180 reason = String.Empty; 5455 reason = String.Empty;
5181 return true; 5456 return true;
5182 } 5457 }
5458
5459 public void StartTimerWatchdog()
5460 {
5461 m_timerWatchdog.Interval = 1000;
5462 m_timerWatchdog.Elapsed += TimerWatchdog;
5463 m_timerWatchdog.AutoReset = true;
5464 m_timerWatchdog.Start();
5465 }
5466
5467 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5468 {
5469 CheckHeartbeat();
5470 }
5183 } 5471 }
5184} 5472}
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index ec94f10..bf861b8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -136,6 +136,8 @@ namespace OpenSim.Region.Framework.Scenes
136 get { return m_permissions; } 136 get { return m_permissions; }
137 } 137 }
138 138
139 protected string m_datastore;
140
139 /* Used by the loadbalancer plugin on GForge */ 141 /* Used by the loadbalancer plugin on GForge */
140 protected RegionStatus m_regStatus; 142 protected RegionStatus m_regStatus;
141 public RegionStatus RegionStatus 143 public RegionStatus RegionStatus
diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
index 837e655..19cb0c1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -44,8 +44,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion;
44 44
45namespace OpenSim.Region.Framework.Scenes 45namespace OpenSim.Region.Framework.Scenes
46{ 46{
47 public delegate void KiPrimitiveDelegate(uint localID);
48
49 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst); 47 public delegate void RemoveKnownRegionsFromAvatarList(UUID avatarID, List<ulong> regionlst);
50 48
51 /// <summary> 49 /// <summary>
@@ -113,8 +111,6 @@ namespace OpenSim.Region.Framework.Scenes
113// private LogOffUser handlerLogOffUser = null; 111// private LogOffUser handlerLogOffUser = null;
114// private GetLandData handlerGetLandData = null; // OnGetLandData 112// private GetLandData handlerGetLandData = null; // OnGetLandData
115 113
116 public KiPrimitiveDelegate KiPrimitive;
117
118 public SceneCommunicationService() 114 public SceneCommunicationService()
119 { 115 {
120 } 116 }
@@ -168,7 +164,7 @@ namespace OpenSim.Region.Framework.Scenes
168 164
169 if (neighbour != null) 165 if (neighbour != null)
170 { 166 {
171 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 167 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
172 m_scene.EventManager.TriggerOnRegionUp(neighbour); 168 m_scene.EventManager.TriggerOnRegionUp(neighbour);
173 } 169 }
174 else 170 else
@@ -183,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes
183 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 179 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
184 180
185 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 181 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
186 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 182 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
187 foreach (GridRegion n in neighbours) 183 foreach (GridRegion n in neighbours)
188 { 184 {
189 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 185 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -259,46 +255,42 @@ namespace OpenSim.Region.Framework.Scenes
259 255
260 } 256 }
261 257
262 //public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle); 258 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
263 //private void SendCloseChildAgentCompleted(IAsyncResult iar)
264 //{
265 // SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
266 // icon.EndInvoke(iar);
267 //}
268 259
269 /// <summary> 260 /// <summary>
270 /// Closes a child agent on a given region 261 /// This Closes child agents on neighboring regions
262 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
271 /// </summary> 263 /// </summary>
272 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 264 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
273 { 265 {
274 266
275 m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle); 267 //m_log.Debug("[INTERGRID]: Sending close agent to " + regionHandle);
276 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 268 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
277 269
278 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID); 270 //m_commsProvider.InterRegion.TellRegionToCloseChildConnection(regionHandle, agentID);
279 uint x = 0, y = 0; 271 uint x = 0, y = 0;
280 Utils.LongToUInts(regionHandle, out x, out y); 272 Utils.LongToUInts(regionHandle, out x, out y);
281 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 273 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
282 m_scene.SimulationService.CloseAgent(destination, agentID); 274 m_scene.SimulationService.CloseChildAgent(destination, agentID);
275 }
276
277 private void SendCloseChildAgentCompleted(IAsyncResult iar)
278 {
279 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
280 icon.EndInvoke(iar);
283 } 281 }
284 282
285 /// <summary>
286 /// Closes a child agents in a collection of regions. Does so asynchronously
287 /// so that the caller doesn't wait.
288 /// </summary>
289 /// <param name="agentID"></param>
290 /// <param name="regionslst"></param>
291 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 283 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
292 { 284 {
293 Util.FireAndForget(delegate 285 foreach (ulong handle in regionslst)
294 { 286 {
295 foreach (ulong handle in regionslst) 287 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
296 { 288 d.BeginInvoke(agentID, handle,
297 SendCloseChildAgent(agentID, handle); 289 SendCloseChildAgentCompleted,
298 } 290 d);
299 }); 291 }
300 } 292 }
301 293
302 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 294 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
303 { 295 {
304 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 296 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 6f963ac..29edf13 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>
@@ -617,7 +682,8 @@ namespace OpenSim.Region.Framework.Scenes
617 682
618 Entities[presence.UUID] = presence; 683 Entities[presence.UUID] = presence;
619 684
620 lock (m_presenceLock) 685 m_scenePresencesLock.EnterWriteLock();
686 try
621 { 687 {
622 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 688 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
623 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 689 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -641,6 +707,10 @@ namespace OpenSim.Region.Framework.Scenes
641 m_scenePresenceMap = newmap; 707 m_scenePresenceMap = newmap;
642 m_scenePresenceArray = newlist; 708 m_scenePresenceArray = newlist;
643 } 709 }
710 finally
711 {
712 m_scenePresencesLock.ExitWriteLock();
713 }
644 } 714 }
645 715
646 /// <summary> 716 /// <summary>
@@ -655,7 +725,8 @@ namespace OpenSim.Region.Framework.Scenes
655 agentID); 725 agentID);
656 } 726 }
657 727
658 lock (m_presenceLock) 728 m_scenePresencesLock.EnterWriteLock();
729 try
659 { 730 {
660 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 731 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
661 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 732 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -677,6 +748,10 @@ namespace OpenSim.Region.Framework.Scenes
677 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 748 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
678 } 749 }
679 } 750 }
751 finally
752 {
753 m_scenePresencesLock.ExitWriteLock();
754 }
680 } 755 }
681 756
682 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 757 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1359,8 +1434,13 @@ namespace OpenSim.Region.Framework.Scenes
1359 { 1434 {
1360 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1435 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1361 { 1436 {
1362 if (m_parentScene.AttachmentsModule != null) 1437 // Set the new attachment point data in the object
1363 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1438 byte attachmentPoint = group.GetAttachmentPoint();
1439 group.UpdateGroupPosition(pos);
1440 group.RootPart.IsAttachment = false;
1441 group.AbsolutePosition = group.RootPart.AttachedPos;
1442 group.SetAttachmentPoint(attachmentPoint);
1443 group.HasGroupChanged = true;
1364 } 1444 }
1365 else 1445 else
1366 { 1446 {
@@ -1624,10 +1704,13 @@ namespace OpenSim.Region.Framework.Scenes
1624 /// <param name="childPrims"></param> 1704 /// <param name="childPrims"></param>
1625 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1705 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1626 { 1706 {
1707 SceneObjectGroup parentGroup = root.ParentGroup;
1708 if (parentGroup == null) return;
1627 Monitor.Enter(m_updateLock); 1709 Monitor.Enter(m_updateLock);
1710
1628 try 1711 try
1629 { 1712 {
1630 SceneObjectGroup parentGroup = root.ParentGroup; 1713 parentGroup.areUpdatesSuspended = true;
1631 1714
1632 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1715 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1633 1716
@@ -1639,9 +1722,14 @@ namespace OpenSim.Region.Framework.Scenes
1639 // Make sure no child prim is set for sale 1722 // Make sure no child prim is set for sale
1640 // So that, on delink, no prims are unwittingly 1723 // So that, on delink, no prims are unwittingly
1641 // left for sale and sold off 1724 // left for sale and sold off
1642 child.RootPart.ObjectSaleType = 0; 1725
1643 child.RootPart.SalePrice = 10; 1726 if (child != null)
1644 childGroups.Add(child); 1727 {
1728 child.RootPart.ObjectSaleType = 0;
1729 child.RootPart.SalePrice = 10;
1730 childGroups.Add(child);
1731 }
1732 }
1645 } 1733 }
1646 1734
1647 foreach (SceneObjectGroup child in childGroups) 1735 foreach (SceneObjectGroup child in childGroups)
@@ -1657,12 +1745,13 @@ namespace OpenSim.Region.Framework.Scenes
1657 // occur on link to invoke this elsewhere (such as object selection) 1745 // occur on link to invoke this elsewhere (such as object selection)
1658 parentGroup.RootPart.CreateSelected = true; 1746 parentGroup.RootPart.CreateSelected = true;
1659 parentGroup.TriggerScriptChangedEvent(Changed.LINK); 1747 parentGroup.TriggerScriptChangedEvent(Changed.LINK);
1660 parentGroup.HasGroupChanged = true;
1661 parentGroup.ScheduleGroupForFullUpdate();
1662
1663 } 1748 }
1664 finally 1749 finally
1665 { 1750 {
1751 parentGroup.areUpdatesSuspended = false;
1752 parentGroup.HasGroupChanged = true;
1753 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1754 parentGroup.ScheduleGroupForFullUpdate();
1666 Monitor.Exit(m_updateLock); 1755 Monitor.Exit(m_updateLock);
1667 } 1756 }
1668 } 1757 }
@@ -1694,21 +1783,24 @@ namespace OpenSim.Region.Framework.Scenes
1694 1783
1695 SceneObjectGroup group = part.ParentGroup; 1784 SceneObjectGroup group = part.ParentGroup;
1696 if (!affectedGroups.Contains(group)) 1785 if (!affectedGroups.Contains(group))
1786 {
1787 group.areUpdatesSuspended = true;
1697 affectedGroups.Add(group); 1788 affectedGroups.Add(group);
1789 }
1698 } 1790 }
1699 } 1791 }
1700 } 1792 }
1701 1793
1702 foreach (SceneObjectPart child in childParts) 1794 if (childParts.Count > 0)
1703 { 1795 {
1704 // Unlink all child parts from their groups 1796 foreach (SceneObjectPart child in childParts)
1705 // 1797 {
1706 child.ParentGroup.DelinkFromGroup(child, true); 1798 // Unlink all child parts from their groups
1707 1799 //
1708 // These are not in affected groups and will not be 1800 child.ParentGroup.DelinkFromGroup(child, true);
1709 // handled further. Do the honors here. 1801 child.ParentGroup.HasGroupChanged = true;
1710 child.ParentGroup.HasGroupChanged = true; 1802 child.ParentGroup.ScheduleGroupForFullUpdate();
1711 child.ParentGroup.ScheduleGroupForFullUpdate(); 1803 }
1712 } 1804 }
1713 1805
1714 foreach (SceneObjectPart root in rootParts) 1806 foreach (SceneObjectPart root in rootParts)
@@ -1718,56 +1810,68 @@ namespace OpenSim.Region.Framework.Scenes
1718 // However, editing linked parts and unlinking may be different 1810 // However, editing linked parts and unlinking may be different
1719 // 1811 //
1720 SceneObjectGroup group = root.ParentGroup; 1812 SceneObjectGroup group = root.ParentGroup;
1813 group.areUpdatesSuspended = true;
1721 1814
1722 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1815 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1723 int numChildren = newSet.Count; 1816 int numChildren = newSet.Count;
1724 1817
1818 if (numChildren == 1)
1819 break;
1820
1725 // If there are prims left in a link set, but the root is 1821 // If there are prims left in a link set, but the root is
1726 // slated for unlink, we need to do this 1822 // slated for unlink, we need to do this
1823 // Unlink the remaining set
1727 // 1824 //
1728 if (numChildren != 1) 1825 bool sendEventsToRemainder = true;
1729 { 1826 if (numChildren > 1)
1730 // Unlink the remaining set 1827 sendEventsToRemainder = false;
1731 //
1732 bool sendEventsToRemainder = true;
1733 if (numChildren > 1)
1734 sendEventsToRemainder = false;
1735 1828
1736 foreach (SceneObjectPart p in newSet) 1829 foreach (SceneObjectPart p in newSet)
1830 {
1831 if (p != group.RootPart)
1737 { 1832 {
1738 if (p != group.RootPart) 1833 group.DelinkFromGroup(p, sendEventsToRemainder);
1739 group.DelinkFromGroup(p, sendEventsToRemainder); 1834 if (numChildren > 2)
1835 {
1836 p.ParentGroup.areUpdatesSuspended = true;
1837 }
1838 else
1839 {
1840 p.ParentGroup.HasGroupChanged = true;
1841 p.ParentGroup.ScheduleGroupForFullUpdate();
1842 }
1740 } 1843 }
1844 }
1845
1846 // If there is more than one prim remaining, we
1847 // need to re-link
1848 //
1849 if (numChildren > 2)
1850 {
1851 // Remove old root
1852 //
1853 if (newSet.Contains(root))
1854 newSet.Remove(root);
1741 1855
1742 // If there is more than one prim remaining, we 1856 // Preserve link ordering
1743 // need to re-link
1744 // 1857 //
1745 if (numChildren > 2) 1858 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1746 { 1859 {
1747 // Remove old root 1860 return a.LinkNum.CompareTo(b.LinkNum);
1748 // 1861 });
1749 if (newSet.Contains(root))
1750 newSet.Remove(root);
1751
1752 // Preserve link ordering
1753 //
1754 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1755 {
1756 return a.LinkNum.CompareTo(b.LinkNum);
1757 });
1758 1862
1759 // Determine new root 1863 // Determine new root
1760 // 1864 //
1761 SceneObjectPart newRoot = newSet[0]; 1865 SceneObjectPart newRoot = newSet[0];
1762 newSet.RemoveAt(0); 1866 newSet.RemoveAt(0);
1763 1867
1764 foreach (SceneObjectPart newChild in newSet) 1868 foreach (SceneObjectPart newChild in newSet)
1765 newChild.UpdateFlag = 0; 1869 newChild.UpdateFlag = 0;
1766 1870
1767 LinkObjects(newRoot, newSet); 1871 newRoot.ParentGroup.areUpdatesSuspended = true;
1768 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1872 LinkObjects(newRoot, newSet);
1769 affectedGroups.Add(newRoot.ParentGroup); 1873 if (!affectedGroups.Contains(newRoot.ParentGroup))
1770 } 1874 affectedGroups.Add(newRoot.ParentGroup);
1771 } 1875 }
1772 } 1876 }
1773 1877
@@ -1775,8 +1879,14 @@ namespace OpenSim.Region.Framework.Scenes
1775 // 1879 //
1776 foreach (SceneObjectGroup g in affectedGroups) 1880 foreach (SceneObjectGroup g in affectedGroups)
1777 { 1881 {
1882 // Child prims that have been unlinked and deleted will
1883 // return unless the root is deleted. This will remove them
1884 // from the database. They will be rewritten immediately,
1885 // minus the rows for the unlinked child prims.
1886 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1778 g.TriggerScriptChangedEvent(Changed.LINK); 1887 g.TriggerScriptChangedEvent(Changed.LINK);
1779 g.HasGroupChanged = true; // Persist 1888 g.HasGroupChanged = true; // Persist
1889 g.areUpdatesSuspended = false;
1780 g.ScheduleGroupForFullUpdate(); 1890 g.ScheduleGroupForFullUpdate();
1781 } 1891 }
1782 } 1892 }
@@ -1894,9 +2004,6 @@ namespace OpenSim.Region.Framework.Scenes
1894 child.ApplyNextOwnerPermissions(); 2004 child.ApplyNextOwnerPermissions();
1895 } 2005 }
1896 } 2006 }
1897
1898 copy.RootPart.ObjectSaleType = 0;
1899 copy.RootPart.SalePrice = 10;
1900 } 2007 }
1901 2008
1902 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2009 // 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 2819545..b1b76dd 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -24,11 +24,12 @@
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Drawing; 30using System.Drawing;
31using System.IO; 31using System.IO;
32using System.Diagnostics;
32using System.Linq; 33using System.Linq;
33using System.Threading; 34using System.Threading;
34using System.Xml; 35using System.Xml;
@@ -105,8 +106,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 106 /// since the group's last persistent backup
106 /// </summary> 107 /// </summary>
107 private bool m_hasGroupChanged = false; 108 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 109 private long timeFirstChanged = 0;
109 private long timeLastChanged; 110 private long timeLastChanged = 0;
111 private long m_maxPersistTime = 0;
112 private long m_minPersistTime = 0;
113 private Random m_rand;
114 private bool m_suspendUpdates;
115 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
116
117 public bool areUpdatesSuspended
118 {
119 get
120 {
121 return m_suspendUpdates;
122 }
123 set
124 {
125 m_suspendUpdates = value;
126 if (!value)
127 {
128 QueueForUpdateCheck();
129 }
130 }
131 }
110 132
111 public bool HasGroupChanged 133 public bool HasGroupChanged
112 { 134 {
@@ -114,9 +136,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 136 {
115 if (value) 137 if (value)
116 { 138 {
139 if (m_isBackedUp)
140 {
141 m_scene.SceneGraph.FireChangeBackup(this);
142 }
117 timeLastChanged = DateTime.Now.Ticks; 143 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 144 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 145 timeFirstChanged = DateTime.Now.Ticks;
146 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
147 {
148 if (m_rand == null)
149 {
150 byte[] val = new byte[16];
151 m_rootPart.UUID.ToBytes(val, 0);
152 m_rand = new Random(BitConverter.ToInt32(val, 0));
153 }
154
155 if (m_scene.GetRootAgentCount() == 0)
156 {
157 //If the region is empty, this change has been made by an automated process
158 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
159
160 float factor = 1.5f + (float)(m_rand.NextDouble());
161 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
162 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
163 }
164 else
165 {
166 //If the region is not empty, we want to obey the minimum and maximum persist times
167 //but add a random factor so we stagger the object persistance a little
168 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
169 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
170 }
171 }
120 } 172 }
121 m_hasGroupChanged = value; 173 m_hasGroupChanged = value;
122 174
@@ -131,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes
131 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since 183 /// Has the group changed due to an unlink operation? We record this in order to optimize deletion, since
132 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation. 184 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 185 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 186 public bool HasGroupChangedDueToDelink { get; set; }
135 187
136 private bool isTimeToPersist() 188 private bool isTimeToPersist()
137 { 189 {
@@ -141,8 +193,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 193 return false;
142 if (m_scene.ShuttingDown) 194 if (m_scene.ShuttingDown)
143 return true; 195 return true;
196
197 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
198 {
199 m_maxPersistTime = m_scene.m_persistAfter;
200 m_minPersistTime = m_scene.m_dontPersistBefore;
201 }
202
144 long currentTime = DateTime.Now.Ticks; 203 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 204
205 if (timeLastChanged == 0) timeLastChanged = currentTime;
206 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
207
208 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 209 return true;
147 return false; 210 return false;
148 } 211 }
@@ -247,10 +310,10 @@ namespace OpenSim.Region.Framework.Scenes
247 310
248 private bool m_scriptListens_atTarget; 311 private bool m_scriptListens_atTarget;
249 private bool m_scriptListens_notAtTarget; 312 private bool m_scriptListens_notAtTarget;
250
251 private bool m_scriptListens_atRotTarget; 313 private bool m_scriptListens_atRotTarget;
252 private bool m_scriptListens_notAtRotTarget; 314 private bool m_scriptListens_notAtRotTarget;
253 315
316 public bool m_dupeInProgress = false;
254 internal Dictionary<UUID, string> m_savedScriptState; 317 internal Dictionary<UUID, string> m_savedScriptState;
255 318
256 #region Properties 319 #region Properties
@@ -286,7 +349,13 @@ namespace OpenSim.Region.Framework.Scenes
286 public virtual Quaternion Rotation 349 public virtual Quaternion Rotation
287 { 350 {
288 get { return m_rotation; } 351 get { return m_rotation; }
289 set { m_rotation = value; } 352 set {
353 foreach(SceneObjectPart p in m_parts.GetArray())
354 {
355 p.StoreUndoState(UndoType.STATE_GROUP_ROTATION);
356 }
357 m_rotation = value;
358 }
290 } 359 }
291 360
292 public Quaternion GroupRotation 361 public Quaternion GroupRotation
@@ -397,7 +466,11 @@ namespace OpenSim.Region.Framework.Scenes
397 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 466 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
398 } 467 }
399 } 468 }
400 469
470 foreach (SceneObjectPart part in m_parts.GetArray())
471 {
472 part.IgnoreUndoUpdate = true;
473 }
401 if (RootPart.GetStatusSandbox()) 474 if (RootPart.GetStatusSandbox())
402 { 475 {
403 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 476 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -411,10 +484,31 @@ namespace OpenSim.Region.Framework.Scenes
411 return; 484 return;
412 } 485 }
413 } 486 }
414
415 SceneObjectPart[] parts = m_parts.GetArray(); 487 SceneObjectPart[] parts = m_parts.GetArray();
416 for (int i = 0; i < parts.Length; i++) 488 foreach (SceneObjectPart part in parts)
417 parts[i].GroupPosition = val; 489 {
490 part.IgnoreUndoUpdate = false;
491 part.StoreUndoState(UndoType.STATE_GROUP_POSITION);
492 part.GroupPosition = val;
493 if (!m_dupeInProgress)
494 {
495 part.TriggerScriptChangedEvent(Changed.POSITION);
496 }
497 }
498 if (!m_dupeInProgress)
499 {
500 foreach (ScenePresence av in m_linkedAvatars)
501 {
502 SceneObjectPart p;
503 if (m_parts.TryGetValue(av.LinkedPrim, out p))
504 {
505 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
506 av.AbsolutePosition += offset;
507 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
508 av.SendAvatarDataToAllAgents();
509 }
510 }
511 }
418 512
419 //if (m_rootPart.PhysActor != null) 513 //if (m_rootPart.PhysActor != null)
420 //{ 514 //{
@@ -573,6 +667,7 @@ namespace OpenSim.Region.Framework.Scenes
573 /// </summary> 667 /// </summary>
574 public SceneObjectGroup() 668 public SceneObjectGroup()
575 { 669 {
670
576 } 671 }
577 672
578 /// <summary> 673 /// <summary>
@@ -589,7 +684,7 @@ namespace OpenSim.Region.Framework.Scenes
589 /// Constructor. This object is added to the scene later via AttachToScene() 684 /// Constructor. This object is added to the scene later via AttachToScene()
590 /// </summary> 685 /// </summary>
591 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 686 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
592 { 687 {
593 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 688 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
594 } 689 }
595 690
@@ -637,6 +732,9 @@ namespace OpenSim.Region.Framework.Scenes
637 /// </summary> 732 /// </summary>
638 public virtual void AttachToBackup() 733 public virtual void AttachToBackup()
639 { 734 {
735 if (IsAttachment) return;
736 m_scene.SceneGraph.FireAttachToBackup(this);
737
640 if (InSceneBackup) 738 if (InSceneBackup)
641 { 739 {
642 //m_log.DebugFormat( 740 //m_log.DebugFormat(
@@ -679,6 +777,9 @@ namespace OpenSim.Region.Framework.Scenes
679 777
680 ApplyPhysics(m_scene.m_physicalPrim); 778 ApplyPhysics(m_scene.m_physicalPrim);
681 779
780 if (RootPart.PhysActor != null)
781 RootPart.Buoyancy = RootPart.Buoyancy;
782
682 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 783 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
683 // for the same object with very different properties. The caller must schedule the update. 784 // for the same object with very different properties. The caller must schedule the update.
684 //ScheduleGroupForFullUpdate(); 785 //ScheduleGroupForFullUpdate();
@@ -724,9 +825,9 @@ namespace OpenSim.Region.Framework.Scenes
724 result.normal = inter.normal; 825 result.normal = inter.normal;
725 result.distance = inter.distance; 826 result.distance = inter.distance;
726 } 827 }
828
727 } 829 }
728 } 830 }
729
730 return result; 831 return result;
731 } 832 }
732 833
@@ -746,17 +847,19 @@ namespace OpenSim.Region.Framework.Scenes
746 minZ = 8192f; 847 minZ = 8192f;
747 848
748 SceneObjectPart[] parts = m_parts.GetArray(); 849 SceneObjectPart[] parts = m_parts.GetArray();
749 for (int i = 0; i < parts.Length; i++) 850 foreach (SceneObjectPart part in parts)
750 { 851 {
751 SceneObjectPart part = parts[i];
752
753 Vector3 worldPos = part.GetWorldPosition(); 852 Vector3 worldPos = part.GetWorldPosition();
754 Vector3 offset = worldPos - AbsolutePosition; 853 Vector3 offset = worldPos - AbsolutePosition;
755 Quaternion worldRot; 854 Quaternion worldRot;
756 if (part.ParentID == 0) 855 if (part.ParentID == 0)
856 {
757 worldRot = part.RotationOffset; 857 worldRot = part.RotationOffset;
858 }
758 else 859 else
860 {
759 worldRot = part.GetWorldRotation(); 861 worldRot = part.GetWorldRotation();
862 }
760 863
761 Vector3 frontTopLeft; 864 Vector3 frontTopLeft;
762 Vector3 frontTopRight; 865 Vector3 frontTopRight;
@@ -768,6 +871,8 @@ namespace OpenSim.Region.Framework.Scenes
768 Vector3 backBottomLeft; 871 Vector3 backBottomLeft;
769 Vector3 backBottomRight; 872 Vector3 backBottomRight;
770 873
874 // Vector3[] corners = new Vector3[8];
875
771 Vector3 orig = Vector3.Zero; 876 Vector3 orig = Vector3.Zero;
772 877
773 frontTopLeft.X = orig.X - (part.Scale.X / 2); 878 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -802,6 +907,38 @@ namespace OpenSim.Region.Framework.Scenes
802 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 907 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
803 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 908 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
804 909
910
911
912 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
913 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
914 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
915 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
916 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
917 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
918 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
919 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
920
921 //for (int i = 0; i < 8; i++)
922 //{
923 // corners[i] = corners[i] * worldRot;
924 // corners[i] += offset;
925
926 // if (corners[i].X > maxX)
927 // maxX = corners[i].X;
928 // if (corners[i].X < minX)
929 // minX = corners[i].X;
930
931 // if (corners[i].Y > maxY)
932 // maxY = corners[i].Y;
933 // if (corners[i].Y < minY)
934 // minY = corners[i].Y;
935
936 // if (corners[i].Z > maxZ)
937 // maxZ = corners[i].Y;
938 // if (corners[i].Z < minZ)
939 // minZ = corners[i].Z;
940 //}
941
805 frontTopLeft = frontTopLeft * worldRot; 942 frontTopLeft = frontTopLeft * worldRot;
806 frontTopRight = frontTopRight * worldRot; 943 frontTopRight = frontTopRight * worldRot;
807 frontBottomLeft = frontBottomLeft * worldRot; 944 frontBottomLeft = frontBottomLeft * worldRot;
@@ -823,6 +960,15 @@ namespace OpenSim.Region.Framework.Scenes
823 backTopLeft += offset; 960 backTopLeft += offset;
824 backTopRight += offset; 961 backTopRight += offset;
825 962
963 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
964 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
965 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
966 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
967 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
968 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
969 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
970 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
971
826 if (frontTopRight.X > maxX) 972 if (frontTopRight.X > maxX)
827 maxX = frontTopRight.X; 973 maxX = frontTopRight.X;
828 if (frontTopLeft.X > maxX) 974 if (frontTopLeft.X > maxX)
@@ -968,15 +1114,20 @@ namespace OpenSim.Region.Framework.Scenes
968 1114
969 public void SaveScriptedState(XmlTextWriter writer) 1115 public void SaveScriptedState(XmlTextWriter writer)
970 { 1116 {
1117 SaveScriptedState(writer, false);
1118 }
1119
1120 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1121 {
971 XmlDocument doc = new XmlDocument(); 1122 XmlDocument doc = new XmlDocument();
972 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1123 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
973 1124
974 SceneObjectPart[] parts = m_parts.GetArray(); 1125 SceneObjectPart[] parts = m_parts.GetArray();
975 for (int i = 0; i < parts.Length; i++) 1126 for (int i = 0; i < parts.Length; i++)
976 { 1127 {
977 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1128 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
978 foreach (KeyValuePair<UUID, string> kvp in pstates) 1129 foreach (KeyValuePair<UUID, string> kvp in pstates)
979 states.Add(kvp.Key, kvp.Value); 1130 states[kvp.Key] = kvp.Value;
980 } 1131 }
981 1132
982 if (states.Count > 0) 1133 if (states.Count > 0)
@@ -995,6 +1146,190 @@ namespace OpenSim.Region.Framework.Scenes
995 } 1146 }
996 } 1147 }
997 1148
1149<<<<<<< HEAD
1150 /// <summary>
1151 /// Add the avatar to this linkset (avatar is sat).
1152 /// </summary>
1153 /// <param name="agentID"></param>
1154 public void AddAvatar(UUID agentID)
1155 {
1156 ScenePresence presence;
1157 if (m_scene.TryGetScenePresence(agentID, out presence))
1158 {
1159 if (!m_linkedAvatars.Contains(presence))
1160 {
1161 m_linkedAvatars.Add(presence);
1162 }
1163 }
1164 }
1165
1166 /// <summary>
1167 /// Delete the avatar from this linkset (avatar is unsat).
1168 /// </summary>
1169 /// <param name="agentID"></param>
1170 public void DeleteAvatar(UUID agentID)
1171 {
1172 ScenePresence presence;
1173 if (m_scene.TryGetScenePresence(agentID, out presence))
1174 {
1175 if (m_linkedAvatars.Contains(presence))
1176 {
1177 m_linkedAvatars.Remove(presence);
1178 }
1179 }
1180 }
1181
1182 /// <summary>
1183 /// Returns the list of linked presences (avatars sat on this group)
1184 /// </summary>
1185 /// <param name="agentID"></param>
1186 public List<ScenePresence> GetLinkedAvatars()
1187 {
1188 return m_linkedAvatars;
1189 }
1190
1191 /// <summary>
1192 /// Attach this scene object to the given avatar.
1193 /// </summary>
1194 /// <param name="agentID"></param>
1195 /// <param name="attachmentpoint"></param>
1196 /// <param name="AttachOffset"></param>
1197 public void AttachToAgent(UUID agentID, uint attachmentpoint, Vector3 AttachOffset, bool silent)
1198 {
1199 ScenePresence avatar = m_scene.GetScenePresence(agentID);
1200 if (avatar != null)
1201 {
1202 // don't attach attachments to child agents
1203 if (avatar.IsChildAgent) return;
1204
1205// m_log.DebugFormat("[SOG]: Adding attachment {0} to avatar {1}", Name, avatar.Name);
1206
1207 DetachFromBackup();
1208
1209 // Remove from database and parcel prim count
1210 m_scene.DeleteFromStorage(UUID);
1211 m_scene.EventManager.TriggerParcelPrimCountTainted();
1212
1213 m_rootPart.AttachedAvatar = agentID;
1214
1215 //Anakin Lohner bug #3839
1216 lock (m_parts)
1217 {
1218 foreach (SceneObjectPart p in m_parts.GetArray())
1219 {
1220 p.AttachedAvatar = agentID;
1221 }
1222 }
1223
1224 if (m_rootPart.PhysActor != null)
1225 {
1226 m_scene.PhysicsScene.RemovePrim(m_rootPart.PhysActor);
1227 m_rootPart.PhysActor = null;
1228 }
1229
1230 AbsolutePosition = AttachOffset;
1231 m_rootPart.AttachedPos = AttachOffset;
1232 m_rootPart.IsAttachment = true;
1233
1234 m_rootPart.SetParentLocalId(avatar.LocalId);
1235 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
1236
1237 avatar.AddAttachment(this);
1238
1239 if (!silent)
1240 {
1241 // Killing it here will cause the client to deselect it
1242 // It then reappears on the avatar, deselected
1243 // through the full update below
1244 //
1245 if (IsSelected)
1246 {
1247 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1248 }
1249
1250 IsSelected = false; // fudge....
1251 ScheduleGroupForFullUpdate();
1252 }
1253 }
1254 else
1255 {
1256 m_log.WarnFormat(
1257 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1258 UUID, agentID, Scene.RegionInfo.RegionName);
1259 }
1260 }
1261
1262 public byte GetAttachmentPoint()
1263 {
1264 return m_rootPart.Shape.State;
1265 }
1266
1267 public void ClearPartAttachmentData()
1268 {
1269 SetAttachmentPoint((Byte)0);
1270 }
1271
1272 public void DetachToGround()
1273 {
1274 ScenePresence avatar = m_scene.GetScenePresence(m_rootPart.AttachedAvatar);
1275 if (avatar == null)
1276 return;
1277
1278 avatar.RemoveAttachment(this);
1279
1280 Vector3 detachedpos = new Vector3(127f,127f,127f);
1281 if (avatar == null)
1282 return;
1283
1284 detachedpos = avatar.AbsolutePosition;
1285 RootPart.FromItemID = UUID.Zero;
1286
1287 AbsolutePosition = detachedpos;
1288 m_rootPart.AttachedAvatar = UUID.Zero;
1289
1290 SceneObjectPart[] parts = m_parts.GetArray();
1291 for (int i = 0; i < parts.Length; i++)
1292 parts[i].AttachedAvatar = UUID.Zero;
1293
1294 m_rootPart.SetParentLocalId(0);
1295 SetAttachmentPoint((byte)0);
1296 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, m_scene.m_physicalPrim);
1297 HasGroupChanged = true;
1298 RootPart.Rezzed = DateTime.Now;
1299 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1300 AttachToBackup();
1301 m_scene.EventManager.TriggerParcelPrimCountTainted();
1302 m_rootPart.ScheduleFullUpdate();
1303 m_rootPart.ClearUndoState();
1304 }
1305
1306 public void DetachToInventoryPrep()
1307 {
1308 ScenePresence avatar = m_scene.GetScenePresence(m_rootPart.AttachedAvatar);
1309 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1310 if (avatar != null)
1311 {
1312 //detachedpos = avatar.AbsolutePosition;
1313 avatar.RemoveAttachment(this);
1314 }
1315
1316 m_rootPart.AttachedAvatar = UUID.Zero;
1317
1318 SceneObjectPart[] parts = m_parts.GetArray();
1319 for (int i = 0; i < parts.Length; i++)
1320 parts[i].AttachedAvatar = UUID.Zero;
1321
1322 m_rootPart.SetParentLocalId(0);
1323 //m_rootPart.SetAttachmentPoint((byte)0);
1324 m_rootPart.IsAttachment = false;
1325 AbsolutePosition = m_rootPart.AttachedPos;
1326 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1327 //AttachToBackup();
1328 //m_rootPart.ScheduleFullUpdate();
1329 }
1330
1331=======
1332>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
998 /// <summary> 1333 /// <summary>
999 /// 1334 ///
1000 /// </summary> 1335 /// </summary>
@@ -1052,8 +1387,16 @@ namespace OpenSim.Region.Framework.Scenes
1052 public void AddPart(SceneObjectPart part) 1387 public void AddPart(SceneObjectPart part)
1053 { 1388 {
1054 part.SetParent(this); 1389 part.SetParent(this);
1390<<<<<<< HEAD
1391 m_parts.Add(part.UUID, part);
1392
1393 part.LinkNum = m_parts.Count;
1394
1395 if (part.LinkNum == 2 && RootPart != null)
1396=======
1055 part.LinkNum = m_parts.Add(part.UUID, part); 1397 part.LinkNum = m_parts.Add(part.UUID, part);
1056 if (part.LinkNum == 2) 1398 if (part.LinkNum == 2)
1399>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
1057 RootPart.LinkNum = 1; 1400 RootPart.LinkNum = 1;
1058 } 1401 }
1059 1402
@@ -1136,11 +1479,15 @@ namespace OpenSim.Region.Framework.Scenes
1136 1479
1137 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient) 1480 public virtual void OnGrabPart(SceneObjectPart part, Vector3 offsetPos, IClientAPI remoteClient)
1138 { 1481 {
1482<<<<<<< HEAD
1483 part.StoreUndoState(UndoType.STATE_PRIM_ALL);
1484=======
1139// m_log.DebugFormat( 1485// m_log.DebugFormat(
1140// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1486// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1141// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1487// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1142 1488
1143 part.StoreUndoState(); 1489 part.StoreUndoState();
1490>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
1144 part.OnGrab(offsetPos, remoteClient); 1491 part.OnGrab(offsetPos, remoteClient);
1145 } 1492 }
1146 1493
@@ -1160,6 +1507,11 @@ namespace OpenSim.Region.Framework.Scenes
1160 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1507 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1161 public void DeleteGroupFromScene(bool silent) 1508 public void DeleteGroupFromScene(bool silent)
1162 { 1509 {
1510 // We need to keep track of this state in case this group is still queued for backup.
1511 m_isDeleted = true;
1512
1513 DetachFromBackup();
1514
1163 SceneObjectPart[] parts = m_parts.GetArray(); 1515 SceneObjectPart[] parts = m_parts.GetArray();
1164 for (int i = 0; i < parts.Length; i++) 1516 for (int i = 0; i < parts.Length; i++)
1165 { 1517 {
@@ -1171,13 +1523,11 @@ namespace OpenSim.Region.Framework.Scenes
1171 avatar.StandUp(); 1523 avatar.StandUp();
1172 1524
1173 if (!silent) 1525 if (!silent)
1174 {
1175 part.UpdateFlag = 0; 1526 part.UpdateFlag = 0;
1176 if (part == m_rootPart)
1177 avatar.ControllingClient.SendKillObject(m_regionHandle, part.LocalId);
1178 }
1179 }); 1527 });
1180 } 1528 }
1529
1530
1181 } 1531 }
1182 1532
1183 public void AddScriptLPS(int count) 1533 public void AddScriptLPS(int count)
@@ -1274,7 +1624,12 @@ namespace OpenSim.Region.Framework.Scenes
1274 1624
1275 public void SetOwnerId(UUID userId) 1625 public void SetOwnerId(UUID userId)
1276 { 1626 {
1277 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1627 ForEachPart(delegate(SceneObjectPart part)
1628 {
1629
1630 part.OwnerID = userId;
1631
1632 });
1278 } 1633 }
1279 1634
1280 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1635 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1306,11 +1661,17 @@ namespace OpenSim.Region.Framework.Scenes
1306 return; 1661 return;
1307 } 1662 }
1308 1663
1664 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1665 return;
1666
1309 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1667 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1310 // any exception propogate upwards. 1668 // any exception propogate upwards.
1311 try 1669 try
1312 { 1670 {
1313 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1671 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1672 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1673 m_scene.LoadingPrims) // Land may not be valid yet
1674
1314 { 1675 {
1315 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1676 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1316 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1677 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1337,6 +1698,7 @@ namespace OpenSim.Region.Framework.Scenes
1337 } 1698 }
1338 } 1699 }
1339 } 1700 }
1701
1340 } 1702 }
1341 1703
1342 if (m_scene.UseBackup && HasGroupChanged) 1704 if (m_scene.UseBackup && HasGroupChanged)
@@ -1344,6 +1706,20 @@ namespace OpenSim.Region.Framework.Scenes
1344 // don't backup while it's selected or you're asking for changes mid stream. 1706 // don't backup while it's selected or you're asking for changes mid stream.
1345 if (isTimeToPersist() || forcedBackup) 1707 if (isTimeToPersist() || forcedBackup)
1346 { 1708 {
1709 if (m_rootPart.PhysActor != null &&
1710 (!m_rootPart.PhysActor.IsPhysical))
1711 {
1712 // Possible ghost prim
1713 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1714 {
1715 foreach (SceneObjectPart part in m_parts.GetArray())
1716 {
1717 // Re-set physics actor positions and
1718 // orientations
1719 part.GroupPosition = m_rootPart.GroupPosition;
1720 }
1721 }
1722 }
1347// m_log.DebugFormat( 1723// m_log.DebugFormat(
1348// "[SCENE]: Storing {0}, {1} in {2}", 1724// "[SCENE]: Storing {0}, {1} in {2}",
1349// Name, UUID, m_scene.RegionInfo.RegionName); 1725// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1407,58 +1783,101 @@ namespace OpenSim.Region.Framework.Scenes
1407 /// <returns></returns> 1783 /// <returns></returns>
1408 public SceneObjectGroup Copy(bool userExposed) 1784 public SceneObjectGroup Copy(bool userExposed)
1409 { 1785 {
1410 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1786 SceneObjectGroup dupe;
1411 dupe.m_isBackedUp = false; 1787 try
1412 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1788 {
1413 1789 m_dupeInProgress = true;
1414 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 1790 dupe = (SceneObjectGroup)MemberwiseClone();
1415 // attachments do not bordercross while they're being duplicated. This is hacktastic! 1791 dupe.m_isBackedUp = false;
1416 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 1792 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1417 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state 1793
1418 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position, 1794<<<<<<< HEAD
1419 // then restore it's attachment state 1795 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1420 1796 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1421 // This is only necessary when userExposed is false! 1797 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
1422 1798 // unless IsAttachment is true!, so to prevent border crossing, we save it's attachment state
1799 // (which should be false anyway) set it as an Attachment and then set it's Absolute Position,
1800 // then restore it's attachment state
1801=======
1423 bool previousAttachmentStatus = dupe.IsAttachment; 1802 bool previousAttachmentStatus = dupe.IsAttachment;
1424 1803
1425 if (!userExposed) 1804 if (!userExposed)
1426 dupe.IsAttachment = true; 1805 dupe.IsAttachment = true;
1806>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
1427 1807
1428 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); 1808 // This is only necessary when userExposed is false!
1429 1809
1810<<<<<<< HEAD
1811 bool previousAttachmentStatus = dupe.RootPart.IsAttachment;
1812=======
1430 if (!userExposed) 1813 if (!userExposed)
1431 { 1814 {
1432 dupe.IsAttachment = previousAttachmentStatus; 1815 dupe.IsAttachment = previousAttachmentStatus;
1433 } 1816 }
1817>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
1434 1818
1435 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); 1819 if (!userExposed)
1436 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; 1820 dupe.RootPart.IsAttachment = true;
1437 1821
1438 if (userExposed) 1822 dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
1439 dupe.m_rootPart.TrimPermissions();
1440 1823
1441 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 1824 if (!userExposed)
1442
1443 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1444 { 1825 {
1445 return p1.LinkNum.CompareTo(p2.LinkNum); 1826 dupe.RootPart.IsAttachment = previousAttachmentStatus;
1446 } 1827 }
1447 );
1448 1828
1449 foreach (SceneObjectPart part in partList) 1829 dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed);
1450 { 1830 dupe.m_rootPart.LinkNum = m_rootPart.LinkNum;
1451 SceneObjectPart newPart; 1831
1452 if (part.UUID != m_rootPart.UUID) 1832 if (userExposed)
1833 dupe.m_rootPart.TrimPermissions();
1834
1835 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1836
1837 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1838 {
1839 return p1.LinkNum.CompareTo(p2.LinkNum);
1840 }
1841 );
1842
1843 foreach (SceneObjectPart part in partList)
1453 { 1844 {
1454 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 1845 if (part.UUID != m_rootPart.UUID)
1455 newPart.LinkNum = part.LinkNum; 1846 {
1847 SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1848
1849 newPart.LinkNum = part.LinkNum;
1850 }
1851
1852 // Need to duplicate the physics actor as well
1853 if (part.PhysActor != null && userExposed)
1854 {
1855 PrimitiveBaseShape pbs = part.Shape;
1856
1857 part.PhysActor
1858 = m_scene.PhysicsScene.AddPrimShape(
1859 string.Format("{0}/{1}", part.Name, part.UUID),
1860 pbs,
1861 part.AbsolutePosition,
1862 part.Scale,
1863 part.RotationOffset,
1864 part.PhysActor.IsPhysical,
1865 m_localId);
1866 part.PhysActor.SetMaterial((int)part.Material);
1867
1868 part.PhysActor.LocalID = part.LocalId;
1869 part.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1870 }
1456 } 1871 }
1457 else 1872 if (userExposed)
1458 { 1873 {
1459 newPart = dupe.m_rootPart; 1874 dupe.UpdateParentIDs();
1460 } 1875 dupe.HasGroupChanged = true;
1876 dupe.AttachToBackup();
1461 1877
1878<<<<<<< HEAD
1879 ScheduleGroupForFullUpdate();
1880=======
1462 // Need to duplicate the physics actor as well 1881 // Need to duplicate the physics actor as well
1463 if (part.PhysActor != null && userExposed) 1882 if (part.PhysActor != null && userExposed)
1464 { 1883 {
@@ -1475,18 +1894,13 @@ namespace OpenSim.Region.Framework.Scenes
1475 newPart.LocalId); 1894 newPart.LocalId);
1476 1895
1477 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 1896 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true);
1897>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
1478 } 1898 }
1479 } 1899 }
1480 1900 finally
1481 if (userExposed)
1482 { 1901 {
1483 dupe.UpdateParentIDs(); 1902 m_dupeInProgress = false;
1484 dupe.HasGroupChanged = true;
1485 dupe.AttachToBackup();
1486
1487 ScheduleGroupForFullUpdate();
1488 } 1903 }
1489
1490 return dupe; 1904 return dupe;
1491 } 1905 }
1492 1906
@@ -1592,6 +2006,7 @@ namespace OpenSim.Region.Framework.Scenes
1592 return Vector3.Zero; 2006 return Vector3.Zero;
1593 } 2007 }
1594 2008
2009 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1595 public void moveToTarget(Vector3 target, float tau) 2010 public void moveToTarget(Vector3 target, float tau)
1596 { 2011 {
1597 if (IsAttachment) 2012 if (IsAttachment)
@@ -1615,14 +2030,72 @@ namespace OpenSim.Region.Framework.Scenes
1615 2030
1616 public void stopMoveToTarget() 2031 public void stopMoveToTarget()
1617 { 2032 {
2033<<<<<<< HEAD
2034 SceneObjectPart rootpart = m_rootPart;
2035 if (rootpart != null)
2036 {
2037 if (IsAttachment)
2038 {
2039 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2040 if (avatar != null) avatar.StopMoveToPosition();
2041 }
2042 else
2043 {
2044 if (rootpart.PhysActor != null)
2045 {
2046 rootpart.PhysActor.PIDActive = false;
2047 }
2048 }
2049 }
2050=======
1618 if (RootPart.PhysActor != null) 2051 if (RootPart.PhysActor != null)
1619 RootPart.PhysActor.PIDActive = false; 2052 RootPart.PhysActor.PIDActive = false;
2053>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
1620 } 2054 }
1621 2055
2056 public void rotLookAt(Quaternion target, float strength, float damping)
2057 {
2058 SceneObjectPart rootpart = m_rootPart;
2059 if (rootpart != null)
2060 {
2061 if (IsAttachment)
2062 {
2063 /*
2064 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2065 if (avatar != null)
2066 {
2067 Rotate the Av?
2068 } */
2069 }
2070 else
2071 {
2072 if (rootpart.PhysActor != null)
2073 { // APID must be implemented in your physics system for this to function.
2074 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2075 rootpart.PhysActor.APIDStrength = strength;
2076 rootpart.PhysActor.APIDDamping = damping;
2077 rootpart.PhysActor.APIDActive = true;
2078 }
2079 }
2080 }
2081 }
2082
1622 public void stopLookAt() 2083 public void stopLookAt()
1623 { 2084 {
2085<<<<<<< HEAD
2086 SceneObjectPart rootpart = m_rootPart;
2087 if (rootpart != null)
2088 {
2089 if (rootpart.PhysActor != null)
2090 { // APID must be implemented in your physics system for this to function.
2091 rootpart.PhysActor.APIDActive = false;
2092 }
2093 }
2094
2095=======
1624 if (RootPart.PhysActor != null) 2096 if (RootPart.PhysActor != null)
1625 RootPart.PhysActor.APIDActive = false; 2097 RootPart.PhysActor.APIDActive = false;
2098>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
1626 } 2099 }
1627 2100
1628 /// <summary> 2101 /// <summary>
@@ -1680,6 +2153,8 @@ namespace OpenSim.Region.Framework.Scenes
1680 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2153 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1681 { 2154 {
1682 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2155 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2156 newPart.SetParent(this);
2157
1683 AddPart(newPart); 2158 AddPart(newPart);
1684 2159
1685 SetPartAsNonRoot(newPart); 2160 SetPartAsNonRoot(newPart);
@@ -1828,11 +2303,11 @@ namespace OpenSim.Region.Framework.Scenes
1828 /// Immediately send a full update for this scene object. 2303 /// Immediately send a full update for this scene object.
1829 /// </summary> 2304 /// </summary>
1830 public void SendGroupFullUpdate() 2305 public void SendGroupFullUpdate()
1831 { 2306 {
1832 if (IsDeleted) 2307 if (IsDeleted)
1833 return; 2308 return;
1834 2309
1835// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2310// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1836 2311
1837 RootPart.SendFullUpdateToAllClients(); 2312 RootPart.SendFullUpdateToAllClients();
1838 2313
@@ -2021,12 +2496,15 @@ namespace OpenSim.Region.Framework.Scenes
2021 part.LinkNum += objectGroup.PrimCount; 2496 part.LinkNum += objectGroup.PrimCount;
2022 } 2497 }
2023 } 2498 }
2499 }
2024 2500
2025 linkPart.LinkNum = 2; 2501 linkPart.LinkNum = 2;
2026 2502
2027 linkPart.SetParent(this); 2503 linkPart.SetParent(this);
2028 linkPart.CreateSelected = true; 2504 linkPart.CreateSelected = true;
2029 2505
2506 lock (m_parts.SyncRoot)
2507 {
2030 //if (linkPart.PhysActor != null) 2508 //if (linkPart.PhysActor != null)
2031 //{ 2509 //{
2032 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor); 2510 // m_scene.PhysicsScene.RemovePrim(linkPart.PhysActor);
@@ -2184,7 +2662,13 @@ namespace OpenSim.Region.Framework.Scenes
2184 /// <param name="objectGroup"></param> 2662 /// <param name="objectGroup"></param>
2185 public virtual void DetachFromBackup() 2663 public virtual void DetachFromBackup()
2186 { 2664 {
2665<<<<<<< HEAD
2666 m_scene.SceneGraph.FireDetachFromBackup(this);
2667
2668 if (m_isBackedUp)
2669=======
2187 if (m_isBackedUp && Scene != null) 2670 if (m_isBackedUp && Scene != null)
2671>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2188 m_scene.EventManager.OnBackup -= ProcessBackup; 2672 m_scene.EventManager.OnBackup -= ProcessBackup;
2189 2673
2190 m_isBackedUp = false; 2674 m_isBackedUp = false;
@@ -2202,7 +2686,8 @@ namespace OpenSim.Region.Framework.Scenes
2202 2686
2203 axPos *= parentRot; 2687 axPos *= parentRot;
2204 part.OffsetPosition = axPos; 2688 part.OffsetPosition = axPos;
2205 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2689 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2690 part.GroupPosition = newPos;
2206 part.OffsetPosition = Vector3.Zero; 2691 part.OffsetPosition = Vector3.Zero;
2207 part.RotationOffset = worldRot; 2692 part.RotationOffset = worldRot;
2208 2693
@@ -2213,7 +2698,7 @@ namespace OpenSim.Region.Framework.Scenes
2213 2698
2214 part.LinkNum = linkNum; 2699 part.LinkNum = linkNum;
2215 2700
2216 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2701 part.OffsetPosition = newPos - AbsolutePosition;
2217 2702
2218 Quaternion rootRotation = m_rootPart.RotationOffset; 2703 Quaternion rootRotation = m_rootPart.RotationOffset;
2219 2704
@@ -2223,7 +2708,7 @@ namespace OpenSim.Region.Framework.Scenes
2223 2708
2224 parentRot = m_rootPart.RotationOffset; 2709 parentRot = m_rootPart.RotationOffset;
2225 oldRot = part.RotationOffset; 2710 oldRot = part.RotationOffset;
2226 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2711 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2227 part.RotationOffset = newRot; 2712 part.RotationOffset = newRot;
2228 } 2713 }
2229 2714
@@ -2479,8 +2964,16 @@ namespace OpenSim.Region.Framework.Scenes
2479 } 2964 }
2480 } 2965 }
2481 2966
2967 RootPart.UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2482 for (int i = 0; i < parts.Length; i++) 2968 for (int i = 0; i < parts.Length; i++)
2969<<<<<<< HEAD
2970 {
2971 if (parts[i] != RootPart)
2972 parts[i].UpdatePrimFlags(UsePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
2973 }
2974=======
2483 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 2975 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2976>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2484 } 2977 }
2485 } 2978 }
2486 2979
@@ -2493,6 +2986,17 @@ namespace OpenSim.Region.Framework.Scenes
2493 } 2986 }
2494 } 2987 }
2495 2988
2989
2990
2991 /// <summary>
2992 /// Gets the number of parts
2993 /// </summary>
2994 /// <returns></returns>
2995 public int GetPartCount()
2996 {
2997 return Parts.Count();
2998 }
2999
2496 /// <summary> 3000 /// <summary>
2497 /// Update the texture entry for this part 3001 /// Update the texture entry for this part
2498 /// </summary> 3002 /// </summary>
@@ -2547,10 +3051,37 @@ namespace OpenSim.Region.Framework.Scenes
2547 /// <param name="scale"></param> 3051 /// <param name="scale"></param>
2548 public void GroupResize(Vector3 scale) 3052 public void GroupResize(Vector3 scale)
2549 { 3053 {
3054<<<<<<< HEAD
3055 if (scale.X > m_scene.m_maxNonphys)
3056 scale.X = m_scene.m_maxNonphys;
3057 if (scale.Y > m_scene.m_maxNonphys)
3058 scale.Y = m_scene.m_maxNonphys;
3059 if (scale.Z > m_scene.m_maxNonphys)
3060 scale.Z = m_scene.m_maxNonphys;
3061 SceneObjectPart part = GetChildPart(localID);
3062 if (part != null)
3063 {
3064 if (part.PhysActor != null)
3065 {
3066 if (part.PhysActor.IsPhysical)
3067 {
3068 if (scale.X > m_scene.m_maxPhys)
3069 scale.X = m_scene.m_maxPhys;
3070 if (scale.Y > m_scene.m_maxPhys)
3071 scale.Y = m_scene.m_maxPhys;
3072 if (scale.Z > m_scene.m_maxPhys)
3073 scale.Z = m_scene.m_maxPhys;
3074 }
3075 part.PhysActor.Size = scale;
3076 m_scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
3077 }
3078 part.Resize(scale);
3079=======
2550// m_log.DebugFormat( 3080// m_log.DebugFormat(
2551// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); 3081// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2552 3082
2553 RootPart.StoreUndoState(true); 3083 RootPart.StoreUndoState(true);
3084>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2554 3085
2555 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3086 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2556 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3087 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
@@ -2563,9 +3094,35 @@ namespace OpenSim.Region.Framework.Scenes
2563 scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); 3094 scale.Z = Math.Min(scale.Z, Scene.m_maxPhys);
2564 } 3095 }
2565 3096
3097<<<<<<< HEAD
3098 public void GroupResize(Vector3 scale, uint localID)
3099 {
3100 SceneObjectPart part = GetChildPart(localID);
3101 if (part != null)
3102 {
3103 if (scale.X > m_scene.m_maxNonphys)
3104 scale.X = m_scene.m_maxNonphys;
3105 if (scale.Y > m_scene.m_maxNonphys)
3106 scale.Y = m_scene.m_maxNonphys;
3107 if (scale.Z > m_scene.m_maxNonphys)
3108 scale.Z = m_scene.m_maxNonphys;
3109 if (part.PhysActor != null && part.PhysActor.IsPhysical)
3110 {
3111 if (scale.X > m_scene.m_maxPhys)
3112 scale.X = m_scene.m_maxPhys;
3113 if (scale.Y > m_scene.m_maxPhys)
3114 scale.Y = m_scene.m_maxPhys;
3115 if (scale.Z > m_scene.m_maxPhys)
3116 scale.Z = m_scene.m_maxPhys;
3117 }
3118 float x = (scale.X / part.Scale.X);
3119 float y = (scale.Y / part.Scale.Y);
3120 float z = (scale.Z / part.Scale.Z);
3121=======
2566 float x = (scale.X / RootPart.Scale.X); 3122 float x = (scale.X / RootPart.Scale.X);
2567 float y = (scale.Y / RootPart.Scale.Y); 3123 float y = (scale.Y / RootPart.Scale.Y);
2568 float z = (scale.Z / RootPart.Scale.Z); 3124 float z = (scale.Z / RootPart.Scale.Z);
3125>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2569 3126
2570 SceneObjectPart[] parts; 3127 SceneObjectPart[] parts;
2571 if (x > 1.0f || y > 1.0f || z > 1.0f) 3128 if (x > 1.0f || y > 1.0f || z > 1.0f)
@@ -2604,17 +3161,72 @@ namespace OpenSim.Region.Framework.Scenes
2604 3161
2605 if (oldSize.Z * z > m_scene.m_maxPhys) 3162 if (oldSize.Z * z > m_scene.m_maxPhys)
2606 { 3163 {
3164<<<<<<< HEAD
3165 if (oldSize.X*x > m_scene.m_maxPhys)
3166 {
3167 f = m_scene.m_maxPhys / oldSize.X;
3168 a = f / x;
3169 x *= a;
3170 y *= a;
3171 z *= a;
3172 }
3173 if (oldSize.Y*y > m_scene.m_maxPhys)
3174 {
3175 f = m_scene.m_maxPhys / oldSize.Y;
3176 a = f / y;
3177 x *= a;
3178 y *= a;
3179 z *= a;
3180 }
3181 if (oldSize.Z*z > m_scene.m_maxPhys)
3182 {
3183 f = m_scene.m_maxPhys / oldSize.Z;
3184 a = f / z;
3185 x *= a;
3186 y *= a;
3187 z *= a;
3188 }
3189=======
2607 f = m_scene.m_maxPhys / oldSize.Z; 3190 f = m_scene.m_maxPhys / oldSize.Z;
2608 a = f / z; 3191 a = f / z;
2609 x *= a; 3192 x *= a;
2610 y *= a; 3193 y *= a;
2611 z *= a; 3194 z *= a;
3195>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2612 } 3196 }
2613 } 3197 }
2614 else 3198 else
2615 { 3199 {
2616 if (oldSize.X * x > m_scene.m_maxNonphys) 3200 if (oldSize.X * x > m_scene.m_maxNonphys)
2617 { 3201 {
3202<<<<<<< HEAD
3203 if (oldSize.X*x > m_scene.m_maxNonphys)
3204 {
3205 f = m_scene.m_maxNonphys / oldSize.X;
3206 a = f / x;
3207 x *= a;
3208 y *= a;
3209 z *= a;
3210 }
3211 if (oldSize.Y*y > m_scene.m_maxNonphys)
3212 {
3213 f = m_scene.m_maxNonphys / oldSize.Y;
3214 a = f / y;
3215 x *= a;
3216 y *= a;
3217 z *= a;
3218 }
3219 if (oldSize.Z*z > m_scene.m_maxNonphys)
3220 {
3221 f = m_scene.m_maxNonphys / oldSize.Z;
3222 a = f / z;
3223 x *= a;
3224 y *= a;
3225 z *= a;
3226 }
3227 }
3228 obPart.IgnoreUndoUpdate = false;
3229=======
2618 f = m_scene.m_maxNonphys / oldSize.X; 3230 f = m_scene.m_maxNonphys / oldSize.X;
2619 a = f / x; 3231 a = f / x;
2620 x *= a; 3232 x *= a;
@@ -2639,6 +3251,7 @@ namespace OpenSim.Region.Framework.Scenes
2639 y *= a; 3251 y *= a;
2640 z *= a; 3252 z *= a;
2641 } 3253 }
3254>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2642 } 3255 }
2643 3256
2644// obPart.IgnoreUndoUpdate = false; 3257// obPart.IgnoreUndoUpdate = false;
@@ -2646,10 +3259,23 @@ namespace OpenSim.Region.Framework.Scenes
2646 } 3259 }
2647 } 3260 }
2648 3261
3262<<<<<<< HEAD
3263 Vector3 prevScale = part.Scale;
3264 prevScale.X *= x;
3265 prevScale.Y *= y;
3266 prevScale.Z *= z;;
3267
3268 part.IgnoreUndoUpdate = false;
3269 part.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3270 part.IgnoreUndoUpdate = true;
3271 part.Resize(prevScale);
3272 part.IgnoreUndoUpdate = false;
3273=======
2649 Vector3 prevScale = RootPart.Scale; 3274 Vector3 prevScale = RootPart.Scale;
2650 prevScale.X *= x; 3275 prevScale.X *= x;
2651 prevScale.Y *= y; 3276 prevScale.Y *= y;
2652 prevScale.Z *= z; 3277 prevScale.Z *= z;
3278>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2653 3279
2654// RootPart.IgnoreUndoUpdate = true; 3280// RootPart.IgnoreUndoUpdate = true;
2655 RootPart.Resize(prevScale); 3281 RootPart.Resize(prevScale);
@@ -2663,6 +3289,32 @@ namespace OpenSim.Region.Framework.Scenes
2663 if (obPart.UUID != m_rootPart.UUID) 3289 if (obPart.UUID != m_rootPart.UUID)
2664 { 3290 {
2665 obPart.IgnoreUndoUpdate = true; 3291 obPart.IgnoreUndoUpdate = true;
3292<<<<<<< HEAD
3293 if (obPart.UUID != m_rootPart.UUID)
3294 {
3295 if (obPart.UUID != m_rootPart.UUID)
3296 {
3297 obPart.IgnoreUndoUpdate = false;
3298 obPart.StoreUndoState(UndoType.STATE_GROUP_SCALE);
3299 obPart.IgnoreUndoUpdate = true;
3300
3301 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
3302 currentpos.X *= x;
3303 currentpos.Y *= y;
3304 currentpos.Z *= z;
3305 Vector3 newSize = new Vector3(obPart.Scale);
3306 newSize.X *= x;
3307 newSize.Y *= y;
3308 newSize.Z *= z;
3309 obPart.Resize(newSize);
3310 obPart.UpdateOffSet(currentpos);
3311 }
3312 obPart.IgnoreUndoUpdate = false;
3313 }
3314 obPart.IgnoreUndoUpdate = false;
3315 }
3316=======
3317>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2666 3318
2667 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3319 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2668 currentpos.X *= x; 3320 currentpos.X *= x;
@@ -2680,8 +3332,15 @@ namespace OpenSim.Region.Framework.Scenes
2680 obPart.IgnoreUndoUpdate = false; 3332 obPart.IgnoreUndoUpdate = false;
2681 } 3333 }
2682 3334
3335<<<<<<< HEAD
3336 part.IgnoreUndoUpdate = false;
3337 HasGroupChanged = true;
3338 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3339 ScheduleGroupForTerseUpdate();
3340=======
2683// obPart.IgnoreUndoUpdate = false; 3341// obPart.IgnoreUndoUpdate = false;
2684// obPart.StoreUndoState(); 3342// obPart.StoreUndoState();
3343>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2685 } 3344 }
2686 3345
2687// m_log.DebugFormat( 3346// m_log.DebugFormat(
@@ -2698,6 +3357,8 @@ namespace OpenSim.Region.Framework.Scenes
2698 /// <param name="pos"></param> 3357 /// <param name="pos"></param>
2699 public void UpdateGroupPosition(Vector3 pos) 3358 public void UpdateGroupPosition(Vector3 pos)
2700 { 3359 {
3360<<<<<<< HEAD
3361=======
2701// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos); 3362// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2702 3363
2703 RootPart.StoreUndoState(true); 3364 RootPart.StoreUndoState(true);
@@ -2706,10 +3367,12 @@ namespace OpenSim.Region.Framework.Scenes
2706// for (int i = 0; i < parts.Length; i++) 3367// for (int i = 0; i < parts.Length; i++)
2707// parts[i].StoreUndoState(); 3368// parts[i].StoreUndoState();
2708 3369
3370>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2709 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3371 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2710 { 3372 {
2711 if (IsAttachment) 3373 if (IsAttachment)
2712 { 3374 {
3375 m_rootPart.StoreUndoState(UndoType.STATE_GROUP_POSITION);
2713 m_rootPart.AttachedPos = pos; 3376 m_rootPart.AttachedPos = pos;
2714 } 3377 }
2715 if (RootPart.GetStatusSandbox()) 3378 if (RootPart.GetStatusSandbox())
@@ -2741,9 +3404,15 @@ namespace OpenSim.Region.Framework.Scenes
2741 { 3404 {
2742 SceneObjectPart part = GetChildPart(localID); 3405 SceneObjectPart part = GetChildPart(localID);
2743 3406
3407<<<<<<< HEAD
3408 SceneObjectPart[] parts = m_parts.GetArray();
3409 for (int i = 0; i < parts.Length; i++)
3410 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
3411=======
2744// SceneObjectPart[] parts = m_parts.GetArray(); 3412// SceneObjectPart[] parts = m_parts.GetArray();
2745// for (int i = 0; i < parts.Length; i++) 3413// for (int i = 0; i < parts.Length; i++)
2746// parts[i].StoreUndoState(); 3414// parts[i].StoreUndoState();
3415>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2747 3416
2748 if (part != null) 3417 if (part != null)
2749 { 3418 {
@@ -2773,12 +3442,18 @@ namespace OpenSim.Region.Framework.Scenes
2773 /// <param name="pos"></param> 3442 /// <param name="pos"></param>
2774 public void UpdateRootPosition(Vector3 pos) 3443 public void UpdateRootPosition(Vector3 pos)
2775 { 3444 {
3445<<<<<<< HEAD
3446 SceneObjectPart[] parts = m_parts.GetArray();
3447 for (int i = 0; i < parts.Length; i++)
3448 parts[i].StoreUndoState(UndoType.STATE_PRIM_POSITION);
3449=======
2776// m_log.DebugFormat( 3450// m_log.DebugFormat(
2777// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos); 3451// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
2778 3452
2779// SceneObjectPart[] parts = m_parts.GetArray(); 3453// SceneObjectPart[] parts = m_parts.GetArray();
2780// for (int i = 0; i < parts.Length; i++) 3454// for (int i = 0; i < parts.Length; i++)
2781// parts[i].StoreUndoState(); 3455// parts[i].StoreUndoState();
3456>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2782 3457
2783 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3458 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2784 Vector3 oldPos = 3459 Vector3 oldPos =
@@ -2799,10 +3474,27 @@ namespace OpenSim.Region.Framework.Scenes
2799 obPart.OffsetPosition = obPart.OffsetPosition + diff; 3474 obPart.OffsetPosition = obPart.OffsetPosition + diff;
2800 } 3475 }
2801 3476
2802 AbsolutePosition = newPos; 3477 //We have to set undoing here because otherwise an undo state will be saved
3478 if (!m_rootPart.Undoing)
3479 {
3480 m_rootPart.Undoing = true;
3481 AbsolutePosition = newPos;
3482 m_rootPart.Undoing = false;
3483 }
3484 else
3485 {
3486 AbsolutePosition = newPos;
3487 }
2803 3488
2804 HasGroupChanged = true; 3489 HasGroupChanged = true;
2805 ScheduleGroupForTerseUpdate(); 3490 if (m_rootPart.Undoing)
3491 {
3492 ScheduleGroupForFullUpdate();
3493 }
3494 else
3495 {
3496 ScheduleGroupForTerseUpdate();
3497 }
2806 } 3498 }
2807 3499
2808 public void OffsetForNewRegion(Vector3 offset) 3500 public void OffsetForNewRegion(Vector3 offset)
@@ -2820,6 +3512,11 @@ namespace OpenSim.Region.Framework.Scenes
2820 /// <param name="rot"></param> 3512 /// <param name="rot"></param>
2821 public void UpdateGroupRotationR(Quaternion rot) 3513 public void UpdateGroupRotationR(Quaternion rot)
2822 { 3514 {
3515<<<<<<< HEAD
3516 SceneObjectPart[] parts = m_parts.GetArray();
3517 for (int i = 0; i < parts.Length; i++)
3518 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3519=======
2823// m_log.DebugFormat( 3520// m_log.DebugFormat(
2824// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot); 3521// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
2825 3522
@@ -2828,6 +3525,7 @@ namespace OpenSim.Region.Framework.Scenes
2828// parts[i].StoreUndoState(); 3525// parts[i].StoreUndoState();
2829 3526
2830 m_rootPart.StoreUndoState(true); 3527 m_rootPart.StoreUndoState(true);
3528>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2831 3529
2832 m_rootPart.UpdateRotation(rot); 3530 m_rootPart.UpdateRotation(rot);
2833 3531
@@ -2849,6 +3547,11 @@ namespace OpenSim.Region.Framework.Scenes
2849 /// <param name="rot"></param> 3547 /// <param name="rot"></param>
2850 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3548 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
2851 { 3549 {
3550<<<<<<< HEAD
3551 SceneObjectPart[] parts = m_parts.GetArray();
3552 for (int i = 0; i < parts.Length; i++)
3553 parts[i].StoreUndoState(UndoType.STATE_GROUP_ROTATION);
3554=======
2852// m_log.DebugFormat( 3555// m_log.DebugFormat(
2853// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot); 3556// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
2854 3557
@@ -2858,6 +3561,7 @@ namespace OpenSim.Region.Framework.Scenes
2858 3561
2859 RootPart.StoreUndoState(true); 3562 RootPart.StoreUndoState(true);
2860 RootPart.IgnoreUndoUpdate = true; 3563 RootPart.IgnoreUndoUpdate = true;
3564>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2861 3565
2862 m_rootPart.UpdateRotation(rot); 3566 m_rootPart.UpdateRotation(rot);
2863 3567
@@ -2884,10 +3588,9 @@ namespace OpenSim.Region.Framework.Scenes
2884 public void UpdateSingleRotation(Quaternion rot, uint localID) 3588 public void UpdateSingleRotation(Quaternion rot, uint localID)
2885 { 3589 {
2886 SceneObjectPart part = GetChildPart(localID); 3590 SceneObjectPart part = GetChildPart(localID);
2887
2888 SceneObjectPart[] parts = m_parts.GetArray(); 3591 SceneObjectPart[] parts = m_parts.GetArray();
2889 for (int i = 0; i < parts.Length; i++) 3592 for (int i = 0; i < parts.Length; i++)
2890 parts[i].StoreUndoState(); 3593 parts[i].StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2891 3594
2892 if (part != null) 3595 if (part != null)
2893 { 3596 {
@@ -2925,12 +3628,29 @@ namespace OpenSim.Region.Framework.Scenes
2925 if (part.UUID == m_rootPart.UUID) 3628 if (part.UUID == m_rootPart.UUID)
2926 { 3629 {
2927 UpdateRootRotation(rot); 3630 UpdateRootRotation(rot);
2928 AbsolutePosition = pos; 3631 if (!m_rootPart.Undoing)
3632 {
3633 m_rootPart.Undoing = true;
3634 AbsolutePosition = pos;
3635 m_rootPart.Undoing = false;
3636 }
3637 else
3638 {
3639 AbsolutePosition = pos;
3640 }
2929 } 3641 }
2930 else 3642 else
2931 { 3643 {
3644<<<<<<< HEAD
3645 part.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
3646 part.IgnoreUndoUpdate = true;
2932 part.UpdateRotation(rot); 3647 part.UpdateRotation(rot);
2933 part.OffsetPosition = pos; 3648 part.OffsetPosition = pos;
3649 part.IgnoreUndoUpdate = false;
3650=======
3651 part.UpdateRotation(rot);
3652 part.OffsetPosition = pos;
3653>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2934 } 3654 }
2935 3655
2936 part.IgnoreUndoUpdate = false; 3656 part.IgnoreUndoUpdate = false;
@@ -2950,8 +3670,16 @@ namespace OpenSim.Region.Framework.Scenes
2950 Quaternion axRot = rot; 3670 Quaternion axRot = rot;
2951 Quaternion oldParentRot = m_rootPart.RotationOffset; 3671 Quaternion oldParentRot = m_rootPart.RotationOffset;
2952 3672
2953 m_rootPart.StoreUndoState(); 3673 m_rootPart.StoreUndoState(UndoType.STATE_PRIM_ROTATION);
2954 m_rootPart.UpdateRotation(rot); 3674 bool cancelUndo = false;
3675 if (!m_rootPart.Undoing)
3676 {
3677 m_rootPart.Undoing = true;
3678 cancelUndo = true;
3679 }
3680
3681 //Don't use UpdateRotation because it schedules an update prematurely
3682 m_rootPart.RotationOffset = rot;
2955 if (m_rootPart.PhysActor != null) 3683 if (m_rootPart.PhysActor != null)
2956 { 3684 {
2957 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3685 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2966,9 +3694,24 @@ namespace OpenSim.Region.Framework.Scenes
2966 { 3694 {
2967 prim.IgnoreUndoUpdate = true; 3695 prim.IgnoreUndoUpdate = true;
2968 Vector3 axPos = prim.OffsetPosition; 3696 Vector3 axPos = prim.OffsetPosition;
3697
2969 axPos *= oldParentRot; 3698 axPos *= oldParentRot;
2970 axPos *= Quaternion.Inverse(axRot); 3699 axPos *= Quaternion.Inverse(axRot);
2971 prim.OffsetPosition = axPos; 3700 prim.OffsetPosition = axPos;
3701<<<<<<< HEAD
3702
3703 prim.RotationOffset *= Quaternion.Inverse(prim.GetWorldRotation()) * (oldParentRot * prim.RotationOffset);
3704
3705 prim.IgnoreUndoUpdate = false;
3706 }
3707 }
3708 if (cancelUndo == true)
3709 {
3710 m_rootPart.Undoing = false;
3711 }
3712 HasGroupChanged = true;
3713 ScheduleGroupForFullUpdate();
3714=======
2972 Quaternion primsRot = prim.RotationOffset; 3715 Quaternion primsRot = prim.RotationOffset;
2973 Quaternion newRot = primsRot * oldParentRot; 3716 Quaternion newRot = primsRot * oldParentRot;
2974 newRot *= Quaternion.Inverse(axRot); 3717 newRot *= Quaternion.Inverse(axRot);
@@ -2993,6 +3736,7 @@ namespace OpenSim.Region.Framework.Scenes
2993// m_log.DebugFormat( 3736// m_log.DebugFormat(
2994// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3737// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}",
2995// Name, LocalId, rot); 3738// Name, LocalId, rot);
3739>>>>>>> 9f75eaf50e42ef6409fc272ba33a817241907ed8
2996 } 3740 }
2997 3741
2998 #endregion 3742 #endregion
@@ -3216,7 +3960,6 @@ namespace OpenSim.Region.Framework.Scenes
3216 public float GetMass() 3960 public float GetMass()
3217 { 3961 {
3218 float retmass = 0f; 3962 float retmass = 0f;
3219
3220 SceneObjectPart[] parts = m_parts.GetArray(); 3963 SceneObjectPart[] parts = m_parts.GetArray();
3221 for (int i = 0; i < parts.Length; i++) 3964 for (int i = 0; i < parts.Length; i++)
3222 retmass += parts[i].GetMass(); 3965 retmass += parts[i].GetMass();
@@ -3310,6 +4053,14 @@ namespace OpenSim.Region.Framework.Scenes
3310 SetFromItemID(uuid); 4053 SetFromItemID(uuid);
3311 } 4054 }
3312 4055
4056 public void ResetOwnerChangeFlag()
4057 {
4058 ForEachPart(delegate(SceneObjectPart part)
4059 {
4060 part.ResetOwnerChangeFlag();
4061 });
4062 }
4063
3313 #endregion 4064 #endregion
3314 } 4065 }
3315} 4066}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 04fef83..893faf8 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -62,7 +62,8 @@ namespace OpenSim.Region.Framework.Scenes
62 TELEPORT = 512, 62 TELEPORT = 512,
63 REGION_RESTART = 1024, 63 REGION_RESTART = 1024,
64 MEDIA = 2048, 64 MEDIA = 2048,
65 ANIMATION = 16384 65 ANIMATION = 16384,
66 POSITION = 32768
66 } 67 }
67 68
68 // I don't really know where to put this except here. 69 // I don't really know where to put this except here.
@@ -190,7 +191,15 @@ namespace OpenSim.Region.Framework.Scenes
190 191
191 public UUID FromFolderID; 192 public UUID FromFolderID;
192 193
193 194 // The following two are to hold the attachment data
195 // while an object is inworld
196 [XmlIgnore]
197 public byte AttachPoint = 0;
198
199 [XmlIgnore]
200 public Vector3 AttachOffset = Vector3.Zero;
201
202 [XmlIgnore]
194 public int STATUS_ROTATE_X; 203 public int STATUS_ROTATE_X;
195 204
196 205
@@ -272,6 +281,7 @@ namespace OpenSim.Region.Framework.Scenes
272 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 281 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
273 private Vector3 m_sitTargetPosition; 282 private Vector3 m_sitTargetPosition;
274 private string m_sitAnimation = "SIT"; 283 private string m_sitAnimation = "SIT";
284 private bool m_occupied; // KF if any av is sitting on this prim
275 private string m_text = String.Empty; 285 private string m_text = String.Empty;
276 private string m_touchName = String.Empty; 286 private string m_touchName = String.Empty;
277 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 287 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5);
@@ -315,6 +325,7 @@ namespace OpenSim.Region.Framework.Scenes
315 protected Vector3 m_lastAcceleration; 325 protected Vector3 m_lastAcceleration;
316 protected Vector3 m_lastAngularVelocity; 326 protected Vector3 m_lastAngularVelocity;
317 protected int m_lastTerseSent; 327 protected int m_lastTerseSent;
328 protected float m_buoyancy = 0.0f;
318 329
319 /// <summary> 330 /// <summary>
320 /// Stores media texture data 331 /// Stores media texture data
@@ -367,7 +378,7 @@ namespace OpenSim.Region.Framework.Scenes
367 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 378 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
368 Quaternion rotationOffset, Vector3 offsetPosition) 379 Quaternion rotationOffset, Vector3 offsetPosition)
369 { 380 {
370 m_name = "Primitive"; 381 m_name = "Object";
371 382
372 Rezzed = DateTime.UtcNow; 383 Rezzed = DateTime.UtcNow;
373 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 384 _creationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
@@ -422,7 +433,7 @@ namespace OpenSim.Region.Framework.Scenes
422 private uint _ownerMask = (uint)PermissionMask.All; 433 private uint _ownerMask = (uint)PermissionMask.All;
423 private uint _groupMask = (uint)PermissionMask.None; 434 private uint _groupMask = (uint)PermissionMask.None;
424 private uint _everyoneMask = (uint)PermissionMask.None; 435 private uint _everyoneMask = (uint)PermissionMask.None;
425 private uint _nextOwnerMask = (uint)PermissionMask.All; 436 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
426 private PrimFlags _flags = PrimFlags.None; 437 private PrimFlags _flags = PrimFlags.None;
427 private DateTime m_expires; 438 private DateTime m_expires;
428 private DateTime m_rezzed; 439 private DateTime m_rezzed;
@@ -521,12 +532,16 @@ namespace OpenSim.Region.Framework.Scenes
521 } 532 }
522 533
523 /// <value> 534 /// <value>
524 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 535 /// Get the inventory list
525 /// </value> 536 /// </value>
526 public TaskInventoryDictionary TaskInventory 537 public TaskInventoryDictionary TaskInventory
527 { 538 {
528 get { return m_inventory.Items; } 539 get {
529 set { m_inventory.Items = value; } 540 return m_inventory.Items;
541 }
542 set {
543 m_inventory.Items = value;
544 }
530 } 545 }
531 546
532 /// <summary> 547 /// <summary>
@@ -667,14 +682,12 @@ namespace OpenSim.Region.Framework.Scenes
667 set { m_LoopSoundSlavePrims = value; } 682 set { m_LoopSoundSlavePrims = value; }
668 } 683 }
669 684
670
671 public Byte[] TextureAnimation 685 public Byte[] TextureAnimation
672 { 686 {
673 get { return m_TextureAnimation; } 687 get { return m_TextureAnimation; }
674 set { m_TextureAnimation = value; } 688 set { m_TextureAnimation = value; }
675 } 689 }
676 690
677
678 public Byte[] ParticleSystem 691 public Byte[] ParticleSystem
679 { 692 {
680 get { return m_particleSystem; } 693 get { return m_particleSystem; }
@@ -711,9 +724,11 @@ namespace OpenSim.Region.Framework.Scenes
711 { 724 {
712 // If this is a linkset, we don't want the physics engine mucking up our group position here. 725 // If this is a linkset, we don't want the physics engine mucking up our group position here.
713 PhysicsActor actor = PhysActor; 726 PhysicsActor actor = PhysActor;
714 if (actor != null && _parentID == 0) 727 if (_parentID == 0)
715 { 728 {
716 m_groupPosition = actor.Position; 729 if (actor != null)
730 m_groupPosition = actor.Position;
731 return m_groupPosition;
717 } 732 }
718 733
719 if (m_parentGroup.IsAttachment) 734 if (m_parentGroup.IsAttachment)
@@ -723,12 +738,14 @@ namespace OpenSim.Region.Framework.Scenes
723 return sp.AbsolutePosition; 738 return sp.AbsolutePosition;
724 } 739 }
725 740
741 // use root prim's group position. Physics may have updated it
742 if (ParentGroup.RootPart != this)
743 m_groupPosition = ParentGroup.RootPart.GroupPosition;
726 return m_groupPosition; 744 return m_groupPosition;
727 } 745 }
728 set 746 set
729 { 747 {
730 m_groupPosition = value; 748 m_groupPosition = value;
731
732 PhysicsActor actor = PhysActor; 749 PhysicsActor actor = PhysActor;
733 if (actor != null) 750 if (actor != null)
734 { 751 {
@@ -748,22 +765,13 @@ namespace OpenSim.Region.Framework.Scenes
748 765
749 // Tell the physics engines that this prim changed. 766 // Tell the physics engines that this prim changed.
750 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 767 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
768
751 } 769 }
752 catch (Exception e) 770 catch (Exception e)
753 { 771 {
754 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 772 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
755 } 773 }
756 } 774 }
757
758 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
759 if (m_sitTargetAvatar != UUID.Zero)
760 {
761 ScenePresence avatar;
762 if (m_parentGroup.Scene.TryGetScenePresence(m_sitTargetAvatar, out avatar))
763 {
764 avatar.ParentPosition = GetWorldPosition();
765 }
766 }
767 } 775 }
768 } 776 }
769 777
@@ -772,7 +780,7 @@ namespace OpenSim.Region.Framework.Scenes
772 get { return m_offsetPosition; } 780 get { return m_offsetPosition; }
773 set 781 set
774 { 782 {
775// StoreUndoState(); 783 Vector3 oldpos = m_offsetPosition;
776 m_offsetPosition = value; 784 m_offsetPosition = value;
777 785
778 if (ParentGroup != null && !ParentGroup.IsDeleted) 786 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -787,7 +795,22 @@ namespace OpenSim.Region.Framework.Scenes
787 if (m_parentGroup.Scene != null) 795 if (m_parentGroup.Scene != null)
788 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 796 m_parentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
789 } 797 }
798
799 if (!m_parentGroup.m_dupeInProgress)
800 {
801 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
802 foreach (ScenePresence av in avs)
803 {
804 if (av.LinkedPrim == m_uuid)
805 {
806 Vector3 offset = (m_offsetPosition - oldpos);
807 av.OffsetPosition += offset;
808 av.SendAvatarDataToAllAgents();
809 }
810 }
811 }
790 } 812 }
813 TriggerScriptChangedEvent(Changed.POSITION);
791 } 814 }
792 } 815 }
793 816
@@ -829,7 +852,7 @@ namespace OpenSim.Region.Framework.Scenes
829 852
830 set 853 set
831 { 854 {
832 StoreUndoState(); 855 StoreUndoState(UndoType.STATE_PRIM_ROTATION);
833 m_rotationOffset = value; 856 m_rotationOffset = value;
834 857
835 PhysicsActor actor = PhysActor; 858 PhysicsActor actor = PhysActor;
@@ -914,7 +937,16 @@ namespace OpenSim.Region.Framework.Scenes
914 /// <summary></summary> 937 /// <summary></summary>
915 public Vector3 Acceleration 938 public Vector3 Acceleration
916 { 939 {
917 get { return m_acceleration; } 940 get
941 {
942 PhysicsActor actor = PhysActor;
943 if (actor != null)
944 {
945 m_acceleration = actor.Acceleration;
946 }
947 return m_acceleration;
948 }
949
918 set { m_acceleration = value; } 950 set { m_acceleration = value; }
919 } 951 }
920 952
@@ -1245,6 +1277,13 @@ namespace OpenSim.Region.Framework.Scenes
1245 _flags = value; 1277 _flags = value;
1246 } 1278 }
1247 } 1279 }
1280
1281 [XmlIgnore]
1282 public bool IsOccupied // KF If an av is sittingon this prim
1283 {
1284 get { return m_occupied; }
1285 set { m_occupied = value; }
1286 }
1248 1287
1249 1288
1250 public UUID SitTargetAvatar 1289 public UUID SitTargetAvatar
@@ -1303,6 +1342,19 @@ namespace OpenSim.Region.Framework.Scenes
1303 set { m_collisionSoundVolume = value; } 1342 set { m_collisionSoundVolume = value; }
1304 } 1343 }
1305 1344
1345 public float Buoyancy
1346 {
1347 get { return m_buoyancy; }
1348 set
1349 {
1350 m_buoyancy = value;
1351 if (PhysActor != null)
1352 {
1353 PhysActor.Buoyancy = value;
1354 }
1355 }
1356 }
1357
1306 #endregion Public Properties with only Get 1358 #endregion Public Properties with only Get
1307 1359
1308 #region Private Methods 1360 #region Private Methods
@@ -1319,14 +1371,6 @@ namespace OpenSim.Region.Framework.Scenes
1319 } 1371 }
1320 } 1372 }
1321 1373
1322 /// <summary>
1323 /// Clear all pending updates of parts to clients
1324 /// </summary>
1325 private void ClearUpdateSchedule()
1326 {
1327 m_updateFlag = 0;
1328 }
1329
1330 private void SendObjectPropertiesToClient(UUID AgentID) 1374 private void SendObjectPropertiesToClient(UUID AgentID)
1331 { 1375 {
1332 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) 1376 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar)
@@ -1663,6 +1707,9 @@ namespace OpenSim.Region.Framework.Scenes
1663 1707
1664 // Move afterwards ResetIDs as it clears the localID 1708 // Move afterwards ResetIDs as it clears the localID
1665 dupe.LocalId = localID; 1709 dupe.LocalId = localID;
1710 if(dupe.PhysActor != null)
1711 dupe.PhysActor.LocalID = localID;
1712
1666 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1713 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1667 dupe._lastOwnerID = OwnerID; 1714 dupe._lastOwnerID = OwnerID;
1668 1715
@@ -1713,7 +1760,7 @@ namespace OpenSim.Region.Framework.Scenes
1713 PrimitiveBaseShape shape = PrimitiveBaseShape.Create(); 1760 PrimitiveBaseShape shape = PrimitiveBaseShape.Create();
1714 part.Shape = shape; 1761 part.Shape = shape;
1715 1762
1716 part.Name = "Primitive"; 1763 part.Name = "Object";
1717 part._ownerID = UUID.Random(); 1764 part._ownerID = UUID.Random();
1718 1765
1719 return part; 1766 return part;
@@ -2045,19 +2092,17 @@ namespace OpenSim.Region.Framework.Scenes
2045 public Vector3 GetWorldPosition() 2092 public Vector3 GetWorldPosition()
2046 { 2093 {
2047 Quaternion parentRot = ParentGroup.RootPart.RotationOffset; 2094 Quaternion parentRot = ParentGroup.RootPart.RotationOffset;
2048
2049 Vector3 axPos = OffsetPosition; 2095 Vector3 axPos = OffsetPosition;
2050
2051 axPos *= parentRot; 2096 axPos *= parentRot;
2052 Vector3 translationOffsetPosition = axPos; 2097 Vector3 translationOffsetPosition = axPos;
2053 2098 if(_parentID == 0)
2054// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name); 2099 {
2055 2100 return GroupPosition;
2056 Vector3 worldPos = GroupPosition + translationOffsetPosition; 2101 }
2057 2102 else
2058// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name); 2103 {
2059 2104 return ParentGroup.AbsolutePosition + translationOffsetPosition; //KF: Fix child prim position
2060 return worldPos; 2105 }
2061 } 2106 }
2062 2107
2063 /// <summary> 2108 /// <summary>
@@ -2697,17 +2742,18 @@ namespace OpenSim.Region.Framework.Scenes
2697 //Trys to fetch sound id from prim's inventory. 2742 //Trys to fetch sound id from prim's inventory.
2698 //Prim's inventory doesn't support non script items yet 2743 //Prim's inventory doesn't support non script items yet
2699 2744
2700 lock (TaskInventory) 2745 TaskInventory.LockItemsForRead(true);
2746
2747 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2701 { 2748 {
2702 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2749 if (item.Value.Name == sound)
2703 { 2750 {
2704 if (item.Value.Name == sound) 2751 soundID = item.Value.ItemID;
2705 { 2752 break;
2706 soundID = item.Value.ItemID;
2707 break;
2708 }
2709 } 2753 }
2710 } 2754 }
2755
2756 TaskInventory.LockItemsForRead(false);
2711 } 2757 }
2712 2758
2713 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp) 2759 m_parentGroup.Scene.ForEachScenePresence(delegate(ScenePresence sp)
@@ -2792,7 +2838,7 @@ namespace OpenSim.Region.Framework.Scenes
2792 2838
2793 public void RotLookAt(Quaternion target, float strength, float damping) 2839 public void RotLookAt(Quaternion target, float strength, float damping)
2794 { 2840 {
2795 rotLookAt(target, strength, damping); 2841 m_parentGroup.rotLookAt(target, strength, damping); // This calls method in SceneObjectGroup.
2796 } 2842 }
2797 2843
2798 public void rotLookAt(Quaternion target, float strength, float damping) 2844 public void rotLookAt(Quaternion target, float strength, float damping)
@@ -3033,8 +3079,8 @@ namespace OpenSim.Region.Framework.Scenes
3033 { 3079 {
3034 const float ROTATION_TOLERANCE = 0.01f; 3080 const float ROTATION_TOLERANCE = 0.01f;
3035 const float VELOCITY_TOLERANCE = 0.001f; 3081 const float VELOCITY_TOLERANCE = 0.001f;
3036 const float POSITION_TOLERANCE = 0.05f; 3082 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
3037 const int TIME_MS_TOLERANCE = 3000; 3083 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
3038 3084
3039 if (m_updateFlag == 1) 3085 if (m_updateFlag == 1)
3040 { 3086 {
@@ -3048,7 +3094,7 @@ namespace OpenSim.Region.Framework.Scenes
3048 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE) 3094 Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
3049 { 3095 {
3050 AddTerseUpdateToAllAvatars(); 3096 AddTerseUpdateToAllAvatars();
3051 ClearUpdateSchedule(); 3097
3052 3098
3053 // This causes the Scene to 'poll' physical objects every couple of frames 3099 // This causes the Scene to 'poll' physical objects every couple of frames
3054 // bad, so it's been replaced by an event driven method. 3100 // bad, so it's been replaced by an event driven method.
@@ -3066,16 +3112,18 @@ namespace OpenSim.Region.Framework.Scenes
3066 m_lastAngularVelocity = AngularVelocity; 3112 m_lastAngularVelocity = AngularVelocity;
3067 m_lastTerseSent = Environment.TickCount; 3113 m_lastTerseSent = Environment.TickCount;
3068 } 3114 }
3115 //Moved this outside of the if clause so updates don't get blocked.. *sigh*
3116 m_updateFlag = 0; //Why were we calling a function to do this? Inefficient! *screams*
3069 } 3117 }
3070 else 3118 else
3071 { 3119 {
3072 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes 3120 if (m_updateFlag == 2) // is a new prim, just created/reloaded or has major changes
3073 { 3121 {
3074 AddFullUpdateToAllAvatars(); 3122 AddFullUpdateToAllAvatars();
3075 ClearUpdateSchedule(); 3123 m_updateFlag = 0; //Same here
3076 } 3124 }
3077 } 3125 }
3078 ClearUpdateSchedule(); 3126 m_updateFlag = 0;
3079 } 3127 }
3080 3128
3081 /// <summary> 3129 /// <summary>
@@ -3103,17 +3151,16 @@ namespace OpenSim.Region.Framework.Scenes
3103 if (!UUID.TryParse(sound, out soundID)) 3151 if (!UUID.TryParse(sound, out soundID))
3104 { 3152 {
3105 // search sound file from inventory 3153 // search sound file from inventory
3106 lock (TaskInventory) 3154 TaskInventory.LockItemsForRead(true);
3155 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3107 { 3156 {
3108 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3157 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3109 { 3158 {
3110 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3159 soundID = item.Value.ItemID;
3111 { 3160 break;
3112 soundID = item.Value.ItemID;
3113 break;
3114 }
3115 } 3161 }
3116 } 3162 }
3163 TaskInventory.LockItemsForRead(false);
3117 } 3164 }
3118 3165
3119 if (soundID == UUID.Zero) 3166 if (soundID == UUID.Zero)
@@ -3196,14 +3243,6 @@ namespace OpenSim.Region.Framework.Scenes
3196 STATUS_ROTATE_Z = rotate; 3243 STATUS_ROTATE_Z = rotate;
3197 } 3244 }
3198 3245
3199 public void SetBuoyancy(float fvalue)
3200 {
3201 if (PhysActor != null)
3202 {
3203 PhysActor.Buoyancy = fvalue;
3204 }
3205 }
3206
3207 public void SetDieAtEdge(bool p) 3246 public void SetDieAtEdge(bool p)
3208 { 3247 {
3209 if (m_parentGroup.IsDeleted) 3248 if (m_parentGroup.IsDeleted)
@@ -3524,7 +3563,7 @@ namespace OpenSim.Region.Framework.Scenes
3524 3563
3525 public void StopLookAt() 3564 public void StopLookAt()
3526 { 3565 {
3527 m_parentGroup.stopLookAt(); 3566 m_parentGroup.stopLookAt(); // This calls method in SceneObjectGroup.
3528 3567
3529 m_parentGroup.ScheduleGroupForTerseUpdate(); 3568 m_parentGroup.ScheduleGroupForTerseUpdate();
3530 } 3569 }
@@ -3551,8 +3590,7 @@ namespace OpenSim.Region.Framework.Scenes
3551 m_parentGroup.ScheduleGroupForTerseUpdate(); 3590 m_parentGroup.ScheduleGroupForTerseUpdate();
3552 //m_parentGroup.ScheduleGroupForFullUpdate(); 3591 //m_parentGroup.ScheduleGroupForFullUpdate();
3553 } 3592 }
3554 3593 public void StoreUndoState(UndoType type)
3555 public void StoreUndoState()
3556 { 3594 {
3557 StoreUndoState(false); 3595 StoreUndoState(false);
3558 } 3596 }
@@ -3592,6 +3630,18 @@ namespace OpenSim.Region.Framework.Scenes
3592 { 3630 {
3593 UndoState nUndo = new UndoState(this, forGroup); 3631 UndoState nUndo = new UndoState(this, forGroup);
3594 3632
3633 UndoState nUndo = new UndoState(this, type);
3634
3635 if (lastUndo != null)
3636 {
3637 TimeSpan ts = DateTime.Now.Subtract(lastUndo.LastUpdated);
3638 if (ts.TotalMilliseconds < 500)
3639 {
3640 //Delete the last entry since it was less than 500 milliseconds ago
3641 nUndo.Merge(lastUndo);
3642 m_undo.Pop();
3643 }
3644 }
3595 m_undo.Push(nUndo); 3645 m_undo.Push(nUndo);
3596 3646
3597 if (m_redo.Count > 0) 3647 if (m_redo.Count > 0)
@@ -4663,8 +4713,9 @@ namespace OpenSim.Region.Framework.Scenes
4663 { 4713 {
4664 m_shape.TextureEntry = textureEntry; 4714 m_shape.TextureEntry = textureEntry;
4665 TriggerScriptChangedEvent(Changed.TEXTURE); 4715 TriggerScriptChangedEvent(Changed.TEXTURE);
4666 4716 m_updateFlag = 1;
4667 ParentGroup.HasGroupChanged = true; 4717 ParentGroup.HasGroupChanged = true;
4718
4668 //This is madness.. 4719 //This is madness..
4669 //ParentGroup.ScheduleGroupForFullUpdate(); 4720 //ParentGroup.ScheduleGroupForFullUpdate();
4670 //This is sparta 4721 //This is sparta
@@ -4855,5 +4906,17 @@ namespace OpenSim.Region.Framework.Scenes
4855 Color color = Color; 4906 Color color = Color;
4856 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 4907 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4857 } 4908 }
4909
4910 public void ResetOwnerChangeFlag()
4911 {
4912 List<UUID> inv = Inventory.GetInventoryList();
4913
4914 foreach (UUID itemID in inv)
4915 {
4916 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
4917 item.OwnerChanged = false;
4918 Inventory.UpdateInventoryItem(item, false, false);
4919 }
4920 }
4858 } 4921 }
4859} 4922}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index e40e57d..1f0840d 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -48,6 +48,9 @@ namespace OpenSim.Region.Framework.Scenes
48 private string m_inventoryFileName = String.Empty; 48 private string m_inventoryFileName = String.Empty;
49 private byte[] m_inventoryFileData = new byte[0]; 49 private byte[] m_inventoryFileData = new byte[0];
50 private uint m_inventoryFileNameSerial = 0; 50 private uint m_inventoryFileNameSerial = 0;
51 private bool m_inventoryPrivileged = false;
52
53 private Dictionary<UUID, ArrayList> m_scriptErrors = new Dictionary<UUID, ArrayList>();
51 54
52 /// <value> 55 /// <value>
53 /// The part to which the inventory belongs. 56 /// The part to which the inventory belongs.
@@ -84,11 +87,14 @@ namespace OpenSim.Region.Framework.Scenes
84 /// </value> 87 /// </value>
85 protected internal TaskInventoryDictionary Items 88 protected internal TaskInventoryDictionary Items
86 { 89 {
87 get { return m_items; } 90 get {
91 return m_items;
92 }
88 set 93 set
89 { 94 {
90 m_items = value; 95 m_items = value;
91 m_inventorySerial++; 96 m_inventorySerial++;
97 QueryScriptStates();
92 } 98 }
93 } 99 }
94 100
@@ -123,38 +129,45 @@ namespace OpenSim.Region.Framework.Scenes
123 public void ResetInventoryIDs() 129 public void ResetInventoryIDs()
124 { 130 {
125 if (null == m_part) 131 if (null == m_part)
126 return; 132 m_items.LockItemsForWrite(true);
127 133
128 lock (m_items) 134 if (Items.Count == 0)
129 { 135 {
130 if (0 == m_items.Count) 136 m_items.LockItemsForWrite(false);
131 return; 137 return;
138 }
132 139
133 IList<TaskInventoryItem> items = GetInventoryItems(); 140 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
134 m_items.Clear(); 141 Items.Clear();
135 142
136 foreach (TaskInventoryItem item in items) 143 foreach (TaskInventoryItem item in items)
137 { 144 {
138 item.ResetIDs(m_part.UUID); 145 item.ResetIDs(m_part.UUID);
139 m_items.Add(item.ItemID, item); 146 Items.Add(item.ItemID, item);
140 }
141 } 147 }
148 m_items.LockItemsForWrite(false);
142 } 149 }
143 150
144 public void ResetObjectID() 151 public void ResetObjectID()
145 { 152 {
146 lock (Items) 153 m_items.LockItemsForWrite(true);
154
155 if (Items.Count == 0)
147 { 156 {
148 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values); 157 m_items.LockItemsForWrite(false);
149 Items.Clear(); 158 return;
150 159 }
151 foreach (TaskInventoryItem item in items) 160
152 { 161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
153 item.ParentPartID = m_part.UUID; 162 Items.Clear();
154 item.ParentID = m_part.UUID; 163
155 Items.Add(item.ItemID, item); 164 foreach (TaskInventoryItem item in items)
156 } 165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
157 } 169 }
170 m_items.LockItemsForWrite(false);
158 } 171 }
159 172
160 /// <summary> 173 /// <summary>
@@ -163,12 +176,11 @@ namespace OpenSim.Region.Framework.Scenes
163 /// <param name="ownerId"></param> 176 /// <param name="ownerId"></param>
164 public void ChangeInventoryOwner(UUID ownerId) 177 public void ChangeInventoryOwner(UUID ownerId)
165 { 178 {
166 lock (Items) 179 m_items.LockItemsForWrite(true);
180 if (0 == Items.Count)
167 { 181 {
168 if (0 == Items.Count) 182 m_items.LockItemsForWrite(false);
169 { 183 return;
170 return;
171 }
172 } 184 }
173 185
174 HasInventoryChanged = true; 186 HasInventoryChanged = true;
@@ -184,6 +196,7 @@ namespace OpenSim.Region.Framework.Scenes
184 item.PermsGranter = UUID.Zero; 196 item.PermsGranter = UUID.Zero;
185 item.OwnerChanged = true; 197 item.OwnerChanged = true;
186 } 198 }
199 m_items.LockItemsForWrite(false);
187 } 200 }
188 201
189 /// <summary> 202 /// <summary>
@@ -192,12 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
192 /// <param name="groupID"></param> 205 /// <param name="groupID"></param>
193 public void ChangeInventoryGroup(UUID groupID) 206 public void ChangeInventoryGroup(UUID groupID)
194 { 207 {
195 lock (Items) 208 m_items.LockItemsForWrite(true);
209 if (0 == Items.Count)
196 { 210 {
197 if (0 == Items.Count) 211 m_items.LockItemsForWrite(false);
198 { 212 return;
199 return;
200 }
201 } 213 }
202 214
203 // Don't let this set the HasGroupChanged flag for attachments 215 // Don't let this set the HasGroupChanged flag for attachments
@@ -209,12 +221,45 @@ namespace OpenSim.Region.Framework.Scenes
209 m_part.ParentGroup.HasGroupChanged = true; 221 m_part.ParentGroup.HasGroupChanged = true;
210 } 222 }
211 223
212 List<TaskInventoryItem> items = GetInventoryItems(); 224 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
213 foreach (TaskInventoryItem item in items) 225 foreach (TaskInventoryItem item in items)
214 { 226 {
215 if (groupID != item.GroupID) 227 if (groupID != item.GroupID)
228 {
216 item.GroupID = groupID; 229 item.GroupID = groupID;
230 }
217 } 231 }
232 m_items.LockItemsForWrite(false);
233 }
234
235 private void QueryScriptStates()
236 {
237 if (m_part == null || m_part.ParentGroup == null)
238 return;
239
240 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
241 if (engines == null) // No engine at all
242 return;
243
244 Items.LockItemsForRead(true);
245 foreach (TaskInventoryItem item in Items.Values)
246 {
247 if (item.InvType == (int)InventoryType.LSL)
248 {
249 foreach (IScriptModule e in engines)
250 {
251 bool running;
252
253 if (e.HasScript(item.ItemID, out running))
254 {
255 item.ScriptRunning = running;
256 break;
257 }
258 }
259 }
260 }
261
262 Items.LockItemsForRead(false);
218 } 263 }
219 264
220 /// <summary> 265 /// <summary>
@@ -222,9 +267,14 @@ namespace OpenSim.Region.Framework.Scenes
222 /// </summary> 267 /// </summary>
223 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) 268 public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource)
224 { 269 {
225 List<TaskInventoryItem> scripts = GetInventoryScripts(); 270 Items.LockItemsForRead(true);
226 foreach (TaskInventoryItem item in scripts) 271 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
227 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 272 Items.LockItemsForRead(false);
273 foreach (TaskInventoryItem item in items)
274 {
275 if ((int)InventoryType.LSL == item.InvType)
276 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource);
277 }
228 } 278 }
229 279
230 public ArrayList GetScriptErrors(UUID itemID) 280 public ArrayList GetScriptErrors(UUID itemID)
@@ -257,9 +307,18 @@ namespace OpenSim.Region.Framework.Scenes
257 /// </param> 307 /// </param>
258 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 308 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
259 { 309 {
260 List<TaskInventoryItem> scripts = GetInventoryScripts(); 310 Items.LockItemsForRead(true);
261 foreach (TaskInventoryItem item in scripts) 311 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
262 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 312 Items.LockItemsForRead(false);
313
314 foreach (TaskInventoryItem item in items)
315 {
316 if ((int)InventoryType.LSL == item.InvType)
317 {
318 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
319 m_part.RemoveScriptEvents(item.ItemID);
320 }
321 }
263 } 322 }
264 323
265 /// <summary> 324 /// <summary>
@@ -275,7 +334,10 @@ namespace OpenSim.Region.Framework.Scenes
275 // item.Name, item.ItemID, Name, UUID); 334 // item.Name, item.ItemID, Name, UUID);
276 335
277 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 336 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
337 {
338 StoreScriptError(item.ItemID, "no permission");
278 return; 339 return;
340 }
279 341
280 m_part.AddFlag(PrimFlags.Scripted); 342 m_part.AddFlag(PrimFlags.Scripted);
281 343
@@ -284,14 +346,13 @@ namespace OpenSim.Region.Framework.Scenes
284 if (stateSource == 2 && // Prim crossing 346 if (stateSource == 2 && // Prim crossing
285 m_part.ParentGroup.Scene.m_trustBinaries) 347 m_part.ParentGroup.Scene.m_trustBinaries)
286 { 348 {
287 lock (m_items) 349 m_items.LockItemsForWrite(true);
288 { 350 m_items[item.ItemID].PermsMask = 0;
289 m_items[item.ItemID].PermsMask = 0; 351 m_items[item.ItemID].PermsGranter = UUID.Zero;
290 m_items[item.ItemID].PermsGranter = UUID.Zero; 352 m_items.LockItemsForWrite(false);
291 }
292
293 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 353 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
294 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 354 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
355 StoreScriptErrors(item.ItemID, null);
295 m_part.ParentGroup.AddActiveScriptCount(1); 356 m_part.ParentGroup.AddActiveScriptCount(1);
296 m_part.ScheduleFullUpdate(); 357 m_part.ScheduleFullUpdate();
297 return; 358 return;
@@ -300,6 +361,8 @@ namespace OpenSim.Region.Framework.Scenes
300 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 361 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
301 if (null == asset) 362 if (null == asset)
302 { 363 {
364 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
365 StoreScriptError(item.ItemID, msg);
303 m_log.ErrorFormat( 366 m_log.ErrorFormat(
304 "[PRIM INVENTORY]: " + 367 "[PRIM INVENTORY]: " +
305 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 368 "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
@@ -311,15 +374,20 @@ namespace OpenSim.Region.Framework.Scenes
311 if (m_part.ParentGroup.m_savedScriptState != null) 374 if (m_part.ParentGroup.m_savedScriptState != null)
312 RestoreSavedScriptState(item.OldItemID, item.ItemID); 375 RestoreSavedScriptState(item.OldItemID, item.ItemID);
313 376
314 lock (m_items) 377 m_items.LockItemsForWrite(true);
315 { 378
316 m_items[item.ItemID].PermsMask = 0; 379 m_items[item.ItemID].PermsMask = 0;
317 m_items[item.ItemID].PermsGranter = UUID.Zero; 380 m_items[item.ItemID].PermsGranter = UUID.Zero;
318 } 381
382 m_items.LockItemsForWrite(false);
319 383
320 string script = Utils.BytesToString(asset.Data); 384 string script = Utils.BytesToString(asset.Data);
321 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 385 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
322 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 386 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
387 StoreScriptErrors(item.ItemID, null);
388 if (!item.ScriptRunning)
389 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
390 m_part.LocalId, item.ItemID);
323 m_part.ParentGroup.AddActiveScriptCount(1); 391 m_part.ParentGroup.AddActiveScriptCount(1);
324 m_part.ScheduleFullUpdate(); 392 m_part.ScheduleFullUpdate();
325 } 393 }
@@ -383,21 +451,145 @@ namespace OpenSim.Region.Framework.Scenes
383 451
384 /// <summary> 452 /// <summary>
385 /// Start a script which is in this prim's inventory. 453 /// Start a script which is in this prim's inventory.
454 /// Some processing may occur in the background, but this routine returns asap.
386 /// </summary> 455 /// </summary>
387 /// <param name="itemId"> 456 /// <param name="itemId">
388 /// A <see cref="UUID"/> 457 /// A <see cref="UUID"/>
389 /// </param> 458 /// </param>
390 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 459 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
391 { 460 {
392 TaskInventoryItem item = GetInventoryItem(itemId); 461 lock (m_scriptErrors)
393 if (item != null) 462 {
394 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 463 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
464 m_scriptErrors.Remove(itemId);
465 }
466 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
467 }
468
469 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
470 {
471 m_items.LockItemsForRead(true);
472 if (m_items.ContainsKey(itemId))
473 {
474 if (m_items.ContainsKey(itemId))
475 {
476 m_items.LockItemsForRead(false);
477 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
478 }
479 else
480 {
481 m_items.LockItemsForRead(false);
482 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
483 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
484 StoreScriptError(itemId, msg);
485 m_log.ErrorFormat(
486 "[PRIM INVENTORY]: " +
487 "Couldn't start script with ID {0} since it {1}", itemId, msg);
488 }
489 }
395 else 490 else
491 {
492 m_items.LockItemsForRead(false);
493 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
494 StoreScriptError(itemId, msg);
396 m_log.ErrorFormat( 495 m_log.ErrorFormat(
397 "[PRIM INVENTORY]: " + 496 "[PRIM INVENTORY]: " +
398 "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 497 "Couldn't start script with ID {0} since it {1}", itemId, msg);
399 itemId, m_part.Name, m_part.UUID, 498 }
400 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 499
500 }
501
502 /// <summary>
503 /// Start a script which is in this prim's inventory and return any compilation error messages.
504 /// </summary>
505 /// <param name="itemId">
506 /// A <see cref="UUID"/>
507 /// </param>
508 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
509 {
510 ArrayList errors;
511
512 // Indicate to CreateScriptInstanceInternal() we want it to
513 // post any compilation/loading error messages
514 lock (m_scriptErrors)
515 {
516 m_scriptErrors[itemId] = null;
517 }
518
519 // Perform compilation/loading
520 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
521
522 // Wait for and retrieve any errors
523 lock (m_scriptErrors)
524 {
525 while ((errors = m_scriptErrors[itemId]) == null)
526 {
527 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
528 {
529 m_log.ErrorFormat(
530 "[PRIM INVENTORY]: " +
531 "timedout waiting for script {0} errors", itemId);
532 errors = m_scriptErrors[itemId];
533 if (errors == null)
534 {
535 errors = new ArrayList(1);
536 errors.Add("timedout waiting for errors");
537 }
538 break;
539 }
540 }
541 m_scriptErrors.Remove(itemId);
542 }
543 return errors;
544 }
545
546 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
547 private void StoreScriptErrors(UUID itemId, ArrayList errors)
548 {
549 lock (m_scriptErrors)
550 {
551 // If compilation/loading initiated via CreateScriptInstance(),
552 // it does not want the errors, so just get out
553 if (!m_scriptErrors.ContainsKey(itemId))
554 {
555 return;
556 }
557
558 // Initiated via CreateScriptInstanceEr(), if we know what the
559 // errors are, save them and wake CreateScriptInstanceEr().
560 if (errors != null)
561 {
562 m_scriptErrors[itemId] = errors;
563 System.Threading.Monitor.PulseAll(m_scriptErrors);
564 return;
565 }
566 }
567
568 // Initiated via CreateScriptInstanceEr() but we don't know what
569 // the errors are yet, so retrieve them from the script engine.
570 // This may involve some waiting internal to GetScriptErrors().
571 errors = GetScriptErrors(itemId);
572
573 // Get a default non-null value to indicate success.
574 if (errors == null)
575 {
576 errors = new ArrayList();
577 }
578
579 // Post to CreateScriptInstanceEr() and wake it up
580 lock (m_scriptErrors)
581 {
582 m_scriptErrors[itemId] = errors;
583 System.Threading.Monitor.PulseAll(m_scriptErrors);
584 }
585 }
586
587 // Like StoreScriptErrors(), but just posts a single string message
588 private void StoreScriptError(UUID itemId, string message)
589 {
590 ArrayList errors = new ArrayList(1);
591 errors.Add(message);
592 StoreScriptErrors(itemId, errors);
401 } 593 }
402 594
403 /// <summary> 595 /// <summary>
@@ -410,15 +602,7 @@ namespace OpenSim.Region.Framework.Scenes
410 /// </param> 602 /// </param>
411 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 603 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
412 { 604 {
413 bool scriptPresent = false; 605 if (m_items.ContainsKey(itemId))
414
415 lock (m_items)
416 {
417 if (m_items.ContainsKey(itemId))
418 scriptPresent = true;
419 }
420
421 if (scriptPresent)
422 { 606 {
423 if (!sceneObjectBeingDeleted) 607 if (!sceneObjectBeingDeleted)
424 m_part.RemoveScriptEvents(itemId); 608 m_part.RemoveScriptEvents(itemId);
@@ -443,14 +627,16 @@ namespace OpenSim.Region.Framework.Scenes
443 /// <returns></returns> 627 /// <returns></returns>
444 private bool InventoryContainsName(string name) 628 private bool InventoryContainsName(string name)
445 { 629 {
446 lock (m_items) 630 m_items.LockItemsForRead(true);
631 foreach (TaskInventoryItem item in m_items.Values)
447 { 632 {
448 foreach (TaskInventoryItem item in m_items.Values) 633 if (item.Name == name)
449 { 634 {
450 if (item.Name == name) 635 m_items.LockItemsForRead(false);
451 return true; 636 return true;
452 } 637 }
453 } 638 }
639 m_items.LockItemsForRead(false);
454 return false; 640 return false;
455 } 641 }
456 642
@@ -492,8 +678,9 @@ namespace OpenSim.Region.Framework.Scenes
492 /// <param name="item"></param> 678 /// <param name="item"></param>
493 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 679 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
494 { 680 {
495 List<TaskInventoryItem> il = GetInventoryItems(); 681 m_items.LockItemsForRead(true);
496 682 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
683 m_items.LockItemsForRead(false);
497 foreach (TaskInventoryItem i in il) 684 foreach (TaskInventoryItem i in il)
498 { 685 {
499 if (i.Name == item.Name) 686 if (i.Name == item.Name)
@@ -531,14 +718,14 @@ namespace OpenSim.Region.Framework.Scenes
531 item.Name = name; 718 item.Name = name;
532 item.GroupID = m_part.GroupID; 719 item.GroupID = m_part.GroupID;
533 720
534 lock (m_items) 721 m_items.LockItemsForWrite(true);
535 m_items.Add(item.ItemID, item); 722 m_items.Add(item.ItemID, item);
536 723 m_items.LockItemsForWrite(false);
537 if (allowedDrop) 724 if (allowedDrop)
538 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 725 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
539 else 726 else
540 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 727 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
541 728
542 m_inventorySerial++; 729 m_inventorySerial++;
543 //m_inventorySerial += 2; 730 //m_inventorySerial += 2;
544 HasInventoryChanged = true; 731 HasInventoryChanged = true;
@@ -554,15 +741,15 @@ namespace OpenSim.Region.Framework.Scenes
554 /// <param name="items"></param> 741 /// <param name="items"></param>
555 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 742 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
556 { 743 {
557 lock (m_items) 744 m_items.LockItemsForWrite(true);
745 foreach (TaskInventoryItem item in items)
558 { 746 {
559 foreach (TaskInventoryItem item in items) 747 m_items.Add(item.ItemID, item);
560 { 748// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
561 m_items.Add(item.ItemID, item);
562// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
563 }
564 m_inventorySerial++;
565 } 749 }
750 m_items.LockItemsForWrite(false);
751
752 m_inventorySerial++;
566 } 753 }
567 754
568 /// <summary> 755 /// <summary>
@@ -573,10 +760,9 @@ namespace OpenSim.Region.Framework.Scenes
573 public TaskInventoryItem GetInventoryItem(UUID itemId) 760 public TaskInventoryItem GetInventoryItem(UUID itemId)
574 { 761 {
575 TaskInventoryItem item; 762 TaskInventoryItem item;
576 763 m_items.LockItemsForRead(true);
577 lock (m_items) 764 m_items.TryGetValue(itemId, out item);
578 m_items.TryGetValue(itemId, out item); 765 m_items.LockItemsForRead(false);
579
580 return item; 766 return item;
581 } 767 }
582 768
@@ -592,15 +778,16 @@ namespace OpenSim.Region.Framework.Scenes
592 { 778 {
593 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 779 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
594 780
595 lock (m_items) 781 m_items.LockItemsForRead(true);
782
783 foreach (TaskInventoryItem item in m_items.Values)
596 { 784 {
597 foreach (TaskInventoryItem item in m_items.Values) 785 if (item.Name == name)
598 { 786 items.Add(item);
599 if (item.Name == name)
600 items.Add(item);
601 }
602 } 787 }
603 788
789 m_items.LockItemsForRead(false);
790
604 return items; 791 return items;
605 } 792 }
606 793
@@ -619,6 +806,9 @@ namespace OpenSim.Region.Framework.Scenes
619 string xmlData = Utils.BytesToString(rezAsset.Data); 806 string xmlData = Utils.BytesToString(rezAsset.Data);
620 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 807 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
621 808
809 group.RootPart.AttachPoint = group.RootPart.Shape.State;
810 group.RootPart.AttachOffset = group.AbsolutePosition;
811
622 group.ResetIDs(); 812 group.ResetIDs();
623 813
624 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 814 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -693,8 +883,9 @@ namespace OpenSim.Region.Framework.Scenes
693 883
694 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 884 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
695 { 885 {
696 TaskInventoryItem it = GetInventoryItem(item.ItemID); 886 m_items.LockItemsForWrite(true);
697 if (it != null) 887
888 if (m_items.ContainsKey(item.ItemID))
698 { 889 {
699// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 890// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
700 891
@@ -707,14 +898,10 @@ namespace OpenSim.Region.Framework.Scenes
707 item.GroupID = m_part.GroupID; 898 item.GroupID = m_part.GroupID;
708 899
709 if (item.AssetID == UUID.Zero) 900 if (item.AssetID == UUID.Zero)
710 item.AssetID = it.AssetID; 901 item.AssetID = m_items[item.ItemID].AssetID;
711 902
712 lock (m_items) 903 m_items[item.ItemID] = item;
713 { 904 m_inventorySerial++;
714 m_items[item.ItemID] = item;
715 m_inventorySerial++;
716 }
717
718 if (fireScriptEvents) 905 if (fireScriptEvents)
719 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 906 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
720 907
@@ -723,7 +910,7 @@ namespace OpenSim.Region.Framework.Scenes
723 HasInventoryChanged = true; 910 HasInventoryChanged = true;
724 m_part.ParentGroup.HasGroupChanged = true; 911 m_part.ParentGroup.HasGroupChanged = true;
725 } 912 }
726 913 m_items.LockItemsForWrite(false);
727 return true; 914 return true;
728 } 915 }
729 else 916 else
@@ -734,8 +921,9 @@ namespace OpenSim.Region.Framework.Scenes
734 item.ItemID, m_part.Name, m_part.UUID, 921 item.ItemID, m_part.Name, m_part.UUID,
735 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 922 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
736 } 923 }
737 return false; 924 m_items.LockItemsForWrite(false);
738 925
926 return false;
739 } 927 }
740 928
741 /// <summary> 929 /// <summary>
@@ -746,107 +934,68 @@ namespace OpenSim.Region.Framework.Scenes
746 /// in this prim's inventory.</returns> 934 /// in this prim's inventory.</returns>
747 public int RemoveInventoryItem(UUID itemID) 935 public int RemoveInventoryItem(UUID itemID)
748 { 936 {
749 TaskInventoryItem item = GetInventoryItem(itemID); 937 m_items.LockItemsForRead(true);
750 if (item != null) 938
939 if (m_items.ContainsKey(itemID))
751 { 940 {
752 int type = m_items[itemID].InvType; 941 int type = m_items[itemID].InvType;
942 m_items.LockItemsForRead(false);
753 if (type == 10) // Script 943 if (type == 10) // Script
754 { 944 {
755 m_part.RemoveScriptEvents(itemID);
756 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 945 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
757 } 946 }
947 m_items.LockItemsForWrite(true);
758 m_items.Remove(itemID); 948 m_items.Remove(itemID);
949 m_items.LockItemsForWrite(false);
759 m_inventorySerial++; 950 m_inventorySerial++;
760 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 951 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
761 952
762 HasInventoryChanged = true; 953 HasInventoryChanged = true;
763 m_part.ParentGroup.HasGroupChanged = true; 954 m_part.ParentGroup.HasGroupChanged = true;
764 955
765 if (!ContainsScripts()) 956 int scriptcount = 0;
957 m_items.LockItemsForRead(true);
958 foreach (TaskInventoryItem item in m_items.Values)
959 {
960 if (item.Type == 10)
961 {
962 scriptcount++;
963 }
964 }
965 m_items.LockItemsForRead(false);
966
967
968 if (scriptcount <= 0)
969 {
766 m_part.RemFlag(PrimFlags.Scripted); 970 m_part.RemFlag(PrimFlags.Scripted);
971 }
767 972
768 m_part.ScheduleFullUpdate(); 973 m_part.ScheduleFullUpdate();
769 974
770 return type; 975 return type;
771
772 } 976 }
773 else 977 else
774 { 978 {
979 m_items.LockItemsForRead(false);
775 m_log.ErrorFormat( 980 m_log.ErrorFormat(
776 "[PRIM INVENTORY]: " + 981 "[PRIM INVENTORY]: " +
777 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 982 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
778 itemID, m_part.Name, m_part.UUID, 983 itemID, m_part.Name, m_part.UUID);
779 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
780 } 984 }
781 985
782 return -1; 986 return -1;
783 } 987 }
784 988
785 private bool CreateInventoryFile() 989 private bool CreateInventoryFileName()
786 { 990 {
787 if (m_inventoryFileName == String.Empty || 991 if (m_inventoryFileName == String.Empty ||
788 m_inventoryFileNameSerial < m_inventorySerial) 992 m_inventoryFileNameSerial < m_inventorySerial)
789 { 993 {
790 // Something changed, we need to create a new file
791 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 994 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
792 m_inventoryFileNameSerial = m_inventorySerial; 995 m_inventoryFileNameSerial = m_inventorySerial;
793
794 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
795
796 lock (m_items)
797 {
798 foreach (TaskInventoryItem item in m_items.Values)
799 {
800 UUID ownerID = item.OwnerID;
801 uint everyoneMask = 0;
802 uint baseMask = item.BasePermissions;
803 uint ownerMask = item.CurrentPermissions;
804 uint groupMask = item.GroupPermissions;
805
806 invString.AddItemStart();
807 invString.AddNameValueLine("item_id", item.ItemID.ToString());
808 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
809
810 invString.AddPermissionsStart();
811
812 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
813 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
814 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
815 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
816 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
817
818 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
819 invString.AddNameValueLine("owner_id", ownerID.ToString());
820
821 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
822
823 invString.AddNameValueLine("group_id", item.GroupID.ToString());
824 invString.AddSectionEnd();
825
826 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
827 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
828 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
829 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
830
831 invString.AddSaleStart();
832 invString.AddNameValueLine("sale_type", "not");
833 invString.AddNameValueLine("sale_price", "0");
834 invString.AddSectionEnd();
835
836 invString.AddNameValueLine("name", item.Name + "|");
837 invString.AddNameValueLine("desc", item.Description + "|");
838
839 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
840 invString.AddSectionEnd();
841 }
842 }
843
844 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
845
846 return true; 996 return true;
847 } 997 }
848 998
849 // No need to recreate, the existing file is fine
850 return false; 999 return false;
851 } 1000 }
852 1001
@@ -856,26 +1005,99 @@ namespace OpenSim.Region.Framework.Scenes
856 /// <param name="xferManager"></param> 1005 /// <param name="xferManager"></param>
857 public void RequestInventoryFile(IClientAPI client, IXfer xferManager) 1006 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
858 { 1007 {
859 CreateInventoryFile(); 1008 bool changed = CreateInventoryFileName();
1009
1010 bool includeAssets = false;
1011 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1012 includeAssets = true;
1013
1014 if (m_inventoryPrivileged != includeAssets)
1015 changed = true;
1016
1017 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1018
1019 Items.LockItemsForRead(true);
860 1020
861 if (m_inventorySerial == 0) // No inventory 1021 if (m_inventorySerial == 0) // No inventory
862 { 1022 {
863 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1023 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1024 Items.LockItemsForRead(false);
864 return; 1025 return;
865 } 1026 }
866 1027
867 // In principle, we should only do the rest if the inventory changed; 1028 if (!changed)
868 // by sending m_inventorySerial to the client, it ought to know 1029 {
869 // that nothing changed and that it doesn't need to request the file. 1030 if (m_inventoryFileData.Length > 2)
870 // Unfortunately, it doesn't look like the client optimizes this; 1031 {
871 // the client seems to always come back and request the Xfer, 1032 xferManager.AddNewFile(m_inventoryFileName,
872 // no matter what value m_inventorySerial has. 1033 m_inventoryFileData);
1034 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
1035 Util.StringToBytes256(m_inventoryFileName));
1036
1037 Items.LockItemsForRead(false);
1038 return;
1039 }
1040 }
1041
1042 m_inventoryPrivileged = includeAssets;
1043
1044 foreach (TaskInventoryItem item in m_items.Values)
1045 {
1046 UUID ownerID = item.OwnerID;
1047 uint everyoneMask = 0;
1048 uint baseMask = item.BasePermissions;
1049 uint ownerMask = item.CurrentPermissions;
1050 uint groupMask = item.GroupPermissions;
1051
1052 invString.AddItemStart();
1053 invString.AddNameValueLine("item_id", item.ItemID.ToString());
1054 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
1055
1056 invString.AddPermissionsStart();
1057
1058 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1059 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1060 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1061 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1062 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
1063
1064 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
1065 invString.AddNameValueLine("owner_id", ownerID.ToString());
1066
1067 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
1068
1069 invString.AddNameValueLine("group_id", item.GroupID.ToString());
1070 invString.AddSectionEnd();
1071
1072 if (includeAssets)
1073 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1074 else
1075 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1076 invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]);
1077 invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]);
1078 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
1079
1080 invString.AddSaleStart();
1081 invString.AddNameValueLine("sale_type", "not");
1082 invString.AddNameValueLine("sale_price", "0");
1083 invString.AddSectionEnd();
1084
1085 invString.AddNameValueLine("name", item.Name + "|");
1086 invString.AddNameValueLine("desc", item.Description + "|");
1087
1088 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1089 invString.AddSectionEnd();
1090 }
1091
1092 Items.LockItemsForRead(false);
1093
1094 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
873 1095
874 if (m_inventoryFileData.Length > 2) 1096 if (m_inventoryFileData.Length > 2)
875 // Add the file for Xfer 1097 {
876 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData); 1098 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
1099 }
877 1100
878 // Tell the client we're ready to Xfer the file
879 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, 1101 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
880 Util.StringToBytes256(m_inventoryFileName)); 1102 Util.StringToBytes256(m_inventoryFileName));
881 } 1103 }
@@ -888,10 +1110,11 @@ namespace OpenSim.Region.Framework.Scenes
888 { 1110 {
889 if (HasInventoryChanged) 1111 if (HasInventoryChanged)
890 { 1112 {
891 HasInventoryChanged = false; 1113 Items.LockItemsForRead(true);
892 List<TaskInventoryItem> items = GetInventoryItems(); 1114 datastore.StorePrimInventory(m_part.UUID, Items.Values);
893 datastore.StorePrimInventory(m_part.UUID, items); 1115 Items.LockItemsForRead(false);
894 1116
1117 HasInventoryChanged = false;
895 } 1118 }
896 } 1119 }
897 1120
@@ -958,82 +1181,63 @@ namespace OpenSim.Region.Framework.Scenes
958 { 1181 {
959 uint mask=0x7fffffff; 1182 uint mask=0x7fffffff;
960 1183
961 lock (m_items) 1184 foreach (TaskInventoryItem item in m_items.Values)
962 { 1185 {
963 foreach (TaskInventoryItem item in m_items.Values) 1186 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1187 mask &= ~((uint)PermissionMask.Copy >> 13);
1188 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1189 mask &= ~((uint)PermissionMask.Transfer >> 13);
1190 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1191 mask &= ~((uint)PermissionMask.Modify >> 13);
1192
1193 if (item.InvType == (int)InventoryType.Object)
964 { 1194 {
965 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1195 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
966 mask &= ~((uint)PermissionMask.Copy >> 13); 1196 mask &= ~((uint)PermissionMask.Copy >> 13);
967 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1197 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
968 mask &= ~((uint)PermissionMask.Transfer >> 13); 1198 mask &= ~((uint)PermissionMask.Transfer >> 13);
969 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1199 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
970 mask &= ~((uint)PermissionMask.Modify >> 13); 1200 mask &= ~((uint)PermissionMask.Modify >> 13);
971
972 if (item.InvType != (int)InventoryType.Object)
973 {
974 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
975 mask &= ~((uint)PermissionMask.Copy >> 13);
976 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
977 mask &= ~((uint)PermissionMask.Transfer >> 13);
978 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
979 mask &= ~((uint)PermissionMask.Modify >> 13);
980 }
981 else
982 {
983 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
984 mask &= ~((uint)PermissionMask.Copy >> 13);
985 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
986 mask &= ~((uint)PermissionMask.Transfer >> 13);
987 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
988 mask &= ~((uint)PermissionMask.Modify >> 13);
989 }
990
991 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
992 mask &= ~(uint)PermissionMask.Copy;
993 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
994 mask &= ~(uint)PermissionMask.Transfer;
995 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
996 mask &= ~(uint)PermissionMask.Modify;
997 } 1201 }
1202
1203 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1204 mask &= ~(uint)PermissionMask.Copy;
1205 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1206 mask &= ~(uint)PermissionMask.Transfer;
1207 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1208 mask &= ~(uint)PermissionMask.Modify;
998 } 1209 }
999
1000 return mask; 1210 return mask;
1001 } 1211 }
1002 1212
1003 public void ApplyNextOwnerPermissions() 1213 public void ApplyNextOwnerPermissions()
1004 { 1214 {
1005 lock (m_items) 1215 foreach (TaskInventoryItem item in m_items.Values)
1006 { 1216 {
1007 foreach (TaskInventoryItem item in m_items.Values) 1217 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1008 { 1218 {
1009 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1219 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1010 { 1220 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1011 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1221 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1012 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1222 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1013 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1223 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1014 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1224 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1015 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1016 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1017 }
1018 item.CurrentPermissions &= item.NextPermissions;
1019 item.BasePermissions &= item.NextPermissions;
1020 item.EveryonePermissions &= item.NextPermissions;
1021 item.OwnerChanged = true;
1022 item.PermsMask = 0;
1023 item.PermsGranter = UUID.Zero;
1024 } 1225 }
1226 item.OwnerChanged = true;
1227 item.CurrentPermissions &= item.NextPermissions;
1228 item.BasePermissions &= item.NextPermissions;
1229 item.EveryonePermissions &= item.NextPermissions;
1230 item.PermsMask = 0;
1231 item.PermsGranter = UUID.Zero;
1025 } 1232 }
1026 } 1233 }
1027 1234
1028 public void ApplyGodPermissions(uint perms) 1235 public void ApplyGodPermissions(uint perms)
1029 { 1236 {
1030 lock (m_items) 1237 foreach (TaskInventoryItem item in m_items.Values)
1031 { 1238 {
1032 foreach (TaskInventoryItem item in m_items.Values) 1239 item.CurrentPermissions = perms;
1033 { 1240 item.BasePermissions = perms;
1034 item.CurrentPermissions = perms;
1035 item.BasePermissions = perms;
1036 }
1037 } 1241 }
1038 m_inventorySerial++; 1242 m_inventorySerial++;
1039 HasInventoryChanged = true; 1243 HasInventoryChanged = true;
@@ -1041,17 +1245,13 @@ namespace OpenSim.Region.Framework.Scenes
1041 1245
1042 public bool ContainsScripts() 1246 public bool ContainsScripts()
1043 { 1247 {
1044 lock (m_items) 1248 foreach (TaskInventoryItem item in m_items.Values)
1045 { 1249 {
1046 foreach (TaskInventoryItem item in m_items.Values) 1250 if (item.InvType == (int)InventoryType.LSL)
1047 { 1251 {
1048 if (item.InvType == (int)InventoryType.LSL) 1252 return true;
1049 {
1050 return true;
1051 }
1052 } 1253 }
1053 } 1254 }
1054
1055 return false; 1255 return false;
1056 } 1256 }
1057 1257
@@ -1059,11 +1259,8 @@ namespace OpenSim.Region.Framework.Scenes
1059 { 1259 {
1060 List<UUID> ret = new List<UUID>(); 1260 List<UUID> ret = new List<UUID>();
1061 1261
1062 lock (m_items) 1262 foreach (TaskInventoryItem item in m_items.Values)
1063 { 1263 ret.Add(item.ItemID);
1064 foreach (TaskInventoryItem item in m_items.Values)
1065 ret.Add(item.ItemID);
1066 }
1067 1264
1068 return ret; 1265 return ret;
1069 } 1266 }
@@ -1094,6 +1291,11 @@ namespace OpenSim.Region.Framework.Scenes
1094 1291
1095 public Dictionary<UUID, string> GetScriptStates() 1292 public Dictionary<UUID, string> GetScriptStates()
1096 { 1293 {
1294 return GetScriptStates(false);
1295 }
1296
1297 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1298 {
1097 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1299 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1098 1300
1099 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1301 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1104,25 +1306,35 @@ namespace OpenSim.Region.Framework.Scenes
1104 if (engines == null) // No engine at all 1306 if (engines == null) // No engine at all
1105 return ret; 1307 return ret;
1106 1308
1107 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1309 Items.LockItemsForRead(true);
1108 1310 foreach (TaskInventoryItem item in m_items.Values)
1109 foreach (TaskInventoryItem item in scripts)
1110 { 1311 {
1111 foreach (IScriptModule e in engines) 1312 if (item.InvType == (int)InventoryType.LSL)
1112 { 1313 {
1113 if (e != null) 1314 foreach (IScriptModule e in engines)
1114 { 1315 {
1115 string n = e.GetXMLState(item.ItemID); 1316 if (e != null)
1116 if (n != String.Empty)
1117 { 1317 {
1118 if (!ret.ContainsKey(item.ItemID)) 1318 string n = e.GetXMLState(item.ItemID);
1119 ret[item.ItemID] = n; 1319 if (n != String.Empty)
1120 break; 1320 {
1321 if (oldIDs)
1322 {
1323 if (!ret.ContainsKey(item.OldItemID))
1324 ret[item.OldItemID] = n;
1325 }
1326 else
1327 {
1328 if (!ret.ContainsKey(item.ItemID))
1329 ret[item.ItemID] = n;
1330 }
1331 break;
1332 }
1121 } 1333 }
1122 } 1334 }
1123 } 1335 }
1124 } 1336 }
1125 1337 Items.LockItemsForRead(false);
1126 return ret; 1338 return ret;
1127 } 1339 }
1128 1340
@@ -1132,21 +1344,27 @@ namespace OpenSim.Region.Framework.Scenes
1132 if (engines == null) 1344 if (engines == null)
1133 return; 1345 return;
1134 1346
1135 List<TaskInventoryItem> scripts = GetInventoryScripts();
1136 1347
1137 foreach (TaskInventoryItem item in scripts) 1348 Items.LockItemsForRead(true);
1349
1350 foreach (TaskInventoryItem item in m_items.Values)
1138 { 1351 {
1139 foreach (IScriptModule engine in engines) 1352 if (item.InvType == (int)InventoryType.LSL)
1140 { 1353 {
1141 if (engine != null) 1354 foreach (IScriptModule engine in engines)
1142 { 1355 {
1143 if (item.OwnerChanged) 1356 if (engine != null)
1144 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1357 {
1145 item.OwnerChanged = false; 1358 if (item.OwnerChanged)
1146 engine.ResumeScript(item.ItemID); 1359 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1360 item.OwnerChanged = false;
1361 engine.ResumeScript(item.ItemID);
1362 }
1147 } 1363 }
1148 } 1364 }
1149 } 1365 }
1366
1367 Items.LockItemsForRead(false);
1150 } 1368 }
1151 } 1369 }
1152} 1370}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1c283c7..de9b1f3 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Xml;
29using System.Collections.Generic; 30using System.Collections.Generic;
30using System.Reflection; 31using System.Reflection;
31using System.Timers; 32using System.Timers;
@@ -72,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes
72// { 73// {
73// m_log.Debug("[ScenePresence] Destructor called"); 74// m_log.Debug("[ScenePresence] Destructor called");
74// } 75// }
75 76
76 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 77 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
77 78
78 public PresenceType PresenceType { get; private set; } 79 public PresenceType PresenceType { get; private set; }
@@ -89,7 +90,9 @@ namespace OpenSim.Region.Framework.Scenes
89 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 90 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
90 /// issue #1716 91 /// issue #1716
91 /// </summary> 92 /// </summary>
92 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f); 93// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
94 // Value revised by KF 091121 by comparison with SL.
95 private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
93 96
94 /// <summary> 97 /// <summary>
95 /// Movement updates for agents in neighboring regions are sent directly to clients. 98 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -118,6 +121,7 @@ namespace OpenSim.Region.Framework.Scenes
118 /// TODO: For some reason, we effectively have a list both here and in Appearance. Need to work out if this is 121 /// TODO: For some reason, we effectively have a list both here and in Appearance. Need to work out if this is
119 /// necessary. 122 /// necessary.
120 /// </remarks> 123 /// </remarks>
124
121 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>(); 125 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
122 126
123 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>(); 127 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
@@ -127,10 +131,12 @@ namespace OpenSim.Region.Framework.Scenes
127// private SceneObjectGroup proxyObjectGroup; 131// private SceneObjectGroup proxyObjectGroup;
128 //private SceneObjectPart proxyObjectPart = null; 132 //private SceneObjectPart proxyObjectPart = null;
129 public Vector3 lastKnownAllowedPosition; 133 public Vector3 lastKnownAllowedPosition;
130 public bool sentMessageAboutRestrictedParcelFlyingDown;
131 public Vector4 CollisionPlane = Vector4.UnitW; 134 public Vector4 CollisionPlane = Vector4.UnitW;
132 135
136 private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
137 private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
133 private Vector3 m_lastPosition; 138 private Vector3 m_lastPosition;
139 private Vector3 m_lastWorldPosition;
134 private Quaternion m_lastRotation; 140 private Quaternion m_lastRotation;
135 private Vector3 m_lastVelocity; 141 private Vector3 m_lastVelocity;
136 //private int m_lastTerseSent; 142 //private int m_lastTerseSent;
@@ -138,6 +144,11 @@ namespace OpenSim.Region.Framework.Scenes
138 private bool m_updateflag; 144 private bool m_updateflag;
139 private byte m_movementflag; 145 private byte m_movementflag;
140 private Vector3? m_forceToApply; 146 private Vector3? m_forceToApply;
147 private int m_userFlags;
148 public int UserFlags
149 {
150 get { return m_userFlags; }
151 }
141 private TeleportFlags m_teleportFlags; 152 private TeleportFlags m_teleportFlags;
142 public TeleportFlags TeleportFlags 153 public TeleportFlags TeleportFlags
143 { 154 {
@@ -168,9 +179,10 @@ namespace OpenSim.Region.Framework.Scenes
168 private int m_perfMonMS; 179 private int m_perfMonMS;
169 180
170 private bool m_setAlwaysRun; 181 private bool m_setAlwaysRun;
171
172 private bool m_forceFly; 182 private bool m_forceFly;
173 private bool m_flyDisabled; 183 private bool m_flyDisabled;
184 private bool m_flyingOld; // add for fly velocity control
185 public bool m_wasFlying; // add for fly velocity control
174 186
175 private float m_speedModifier = 1.0f; 187 private float m_speedModifier = 1.0f;
176 188
@@ -189,7 +201,8 @@ namespace OpenSim.Region.Framework.Scenes
189 protected RegionInfo m_regionInfo; 201 protected RegionInfo m_regionInfo;
190 protected ulong crossingFromRegion; 202 protected ulong crossingFromRegion;
191 203
192 private readonly Vector3[] Dir_Vectors = new Vector3[9]; 204 private readonly Vector3[] Dir_Vectors = new Vector3[11];
205 private bool m_isNudging = false;
193 206
194 // Position of agent's camera in world (region cordinates) 207 // Position of agent's camera in world (region cordinates)
195 protected Vector3 m_CameraCenter; 208 protected Vector3 m_CameraCenter;
@@ -214,17 +227,25 @@ namespace OpenSim.Region.Framework.Scenes
214 private bool m_autopilotMoving; 227 private bool m_autopilotMoving;
215 private Vector3 m_autoPilotTarget; 228 private Vector3 m_autoPilotTarget;
216 private bool m_sitAtAutoTarget; 229 private bool m_sitAtAutoTarget;
230 private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
217 231
218 private string m_nextSitAnimation = String.Empty; 232 private string m_nextSitAnimation = String.Empty;
219 233
220 //PauPaw:Proper PID Controler for autopilot************ 234 //PauPaw:Proper PID Controler for autopilot************
221 public bool MovingToTarget { get; private set; } 235 public bool MovingToTarget { get; private set; }
222 public Vector3 MoveToPositionTarget { get; private set; } 236 public Vector3 MoveToPositionTarget { get; private set; }
237 private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
223 238
224 private bool m_followCamAuto; 239 private bool m_followCamAuto;
225 240
226 private int m_movementUpdateCount; 241 private int m_movementUpdateCount;
242 private int m_lastColCount = -1; //KF: Look for Collision chnages
243 private int m_updateCount = 0; //KF: Update Anims for a while
244 private static readonly int UPDATE_COUNT = 10; // how many frames to update for
227 private const int NumMovementsBetweenRayCast = 5; 245 private const int NumMovementsBetweenRayCast = 5;
246 private List<uint> m_lastColliders = new List<uint>();
247
248 private object m_syncRoot = new Object();
228 249
229 private bool CameraConstraintActive; 250 private bool CameraConstraintActive;
230 //private int m_moveToPositionStateStatus; 251 //private int m_moveToPositionStateStatus;
@@ -261,7 +282,9 @@ namespace OpenSim.Region.Framework.Scenes
261 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS, 282 DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
262 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG, 283 DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
263 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS, 284 DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
264 DIR_CONTROL_FLAG_BACKWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG, 285 DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
286 DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
287 DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
265 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG 288 DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
266 } 289 }
267 290
@@ -465,7 +488,8 @@ namespace OpenSim.Region.Framework.Scenes
465 get 488 get
466 { 489 {
467 PhysicsActor actor = m_physicsActor; 490 PhysicsActor actor = m_physicsActor;
468 if (actor != null) 491// if (actor != null)
492 if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
469 m_pos = actor.Position; 493 m_pos = actor.Position;
470 else 494 else
471 { 495 {
@@ -487,7 +511,7 @@ namespace OpenSim.Region.Framework.Scenes
487 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID); 511 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
488 if (part != null) 512 if (part != null)
489 { 513 {
490 return m_parentPosition + (m_pos * part.GetWorldRotation()); 514 return part.AbsolutePosition + (m_pos * part.GetWorldRotation());
491 } 515 }
492 else 516 else
493 { 517 {
@@ -514,7 +538,8 @@ namespace OpenSim.Region.Framework.Scenes
514 } 538 }
515 } 539 }
516 540
517 m_pos = value; 541 if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
542 m_pos = value;
518 m_parentPosition = Vector3.Zero; 543 m_parentPosition = Vector3.Zero;
519 } 544 }
520 } 545 }
@@ -558,10 +583,39 @@ namespace OpenSim.Region.Framework.Scenes
558 } 583 }
559 } 584 }
560 585
586 public Quaternion OffsetRotation
587 {
588 get { return m_offsetRotation; }
589 set { m_offsetRotation = value; }
590 }
591
561 public Quaternion Rotation 592 public Quaternion Rotation
562 { 593 {
563 get { return m_bodyRot; } 594 get {
564 set { m_bodyRot = value; } 595 if (m_parentID != 0)
596 {
597 if (m_offsetRotation != null)
598 {
599 return m_offsetRotation;
600 }
601 else
602 {
603 return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
604 }
605
606 }
607 else
608 {
609 return m_bodyRot;
610 }
611 }
612 set {
613 m_bodyRot = value;
614 if (m_parentID != 0)
615 {
616 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
617 }
618 }
565 } 619 }
566 620
567 public Quaternion PreviousRotation 621 public Quaternion PreviousRotation
@@ -586,11 +640,21 @@ namespace OpenSim.Region.Framework.Scenes
586 640
587 private uint m_parentID; 641 private uint m_parentID;
588 642
643
644 private UUID m_linkedPrim;
645
589 public uint ParentID 646 public uint ParentID
590 { 647 {
591 get { return m_parentID; } 648 get { return m_parentID; }
592 set { m_parentID = value; } 649 set { m_parentID = value; }
593 } 650 }
651
652 public UUID LinkedPrim
653 {
654 get { return m_linkedPrim; }
655 set { m_linkedPrim = value; }
656 }
657
594 public float Health 658 public float Health
595 { 659 {
596 get { return m_health; } 660 get { return m_health; }
@@ -725,6 +789,7 @@ namespace OpenSim.Region.Framework.Scenes
725 m_localId = m_scene.AllocateLocalId(); 789 m_localId = m_scene.AllocateLocalId();
726 790
727 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 791 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
792 m_userFlags = account.UserFlags;
728 793
729 if (account != null) 794 if (account != null)
730 m_userLevel = account.UserLevel; 795 m_userLevel = account.UserLevel;
@@ -743,10 +808,7 @@ namespace OpenSim.Region.Framework.Scenes
743 m_reprioritization_timer.AutoReset = false; 808 m_reprioritization_timer.AutoReset = false;
744 809
745 AdjustKnownSeeds(); 810 AdjustKnownSeeds();
746
747 // TODO: I think, this won't send anything, as we are still a child here...
748 Animator.TrySetMovementAnimation("STAND"); 811 Animator.TrySetMovementAnimation("STAND");
749
750 // we created a new ScenePresence (a new child agent) in a fresh region. 812 // we created a new ScenePresence (a new child agent) in a fresh region.
751 // Request info about all the (root) agents in this region 813 // Request info about all the (root) agents in this region
752 // Note: This won't send data *to* other clients in that region (children don't send) 814 // Note: This won't send data *to* other clients in that region (children don't send)
@@ -787,25 +849,47 @@ namespace OpenSim.Region.Framework.Scenes
787 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT 849 Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
788 Dir_Vectors[4] = Vector3.UnitZ; //UP 850 Dir_Vectors[4] = Vector3.UnitZ; //UP
789 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN 851 Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
790 Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge 852 Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
791 Dir_Vectors[6] = Vector3.UnitX*2; //FORWARD 853 Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
792 Dir_Vectors[7] = -Vector3.UnitX; //BACK 854 Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
855 Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
856 Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
793 } 857 }
794 858
795 private Vector3[] GetWalkDirectionVectors() 859 private Vector3[] GetWalkDirectionVectors()
796 { 860 {
797 Vector3[] vector = new Vector3[9]; 861 Vector3[] vector = new Vector3[11];
798 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD 862 vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
799 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK 863 vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
800 vector[2] = Vector3.UnitY; //LEFT 864 vector[2] = Vector3.UnitY; //LEFT
801 vector[3] = -Vector3.UnitY; //RIGHT 865 vector[3] = -Vector3.UnitY; //RIGHT
802 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP 866 vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
803 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN 867 vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
804 vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge 868 vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
805 vector[6] = (new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z) * 2); //FORWARD Nudge 869 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
806 vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK Nudge 870 vector[8] = Vector3.UnitY; //LEFT_NUDGE
871 vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
872 vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
807 return vector; 873 return vector;
808 } 874 }
875
876 private bool[] GetDirectionIsNudge()
877 {
878 bool[] isNudge = new bool[11];
879 isNudge[0] = false; //FORWARD
880 isNudge[1] = false; //BACK
881 isNudge[2] = false; //LEFT
882 isNudge[3] = false; //RIGHT
883 isNudge[4] = false; //UP
884 isNudge[5] = false; //DOWN
885 isNudge[6] = true; //FORWARD_NUDGE
886 isNudge[7] = true; //BACK_NUDGE
887 isNudge[8] = true; //LEFT_NUDGE
888 isNudge[9] = true; //RIGHT_NUDGE
889 isNudge[10] = true; //DOWN_Nudge
890 return isNudge;
891 }
892
809 893
810 #endregion 894 #endregion
811 895
@@ -870,6 +954,62 @@ namespace OpenSim.Region.Framework.Scenes
870 pos.Y = crossedBorder.BorderLine.Z - 1; 954 pos.Y = crossedBorder.BorderLine.Z - 1;
871 } 955 }
872 956
957 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
958 if (land != null)
959 {
960 // If we come in via login, landmark or map, we want to
961 // honor landing points. If we come in via Lure, we want
962 // to ignore them.
963 if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) ||
964 (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 ||
965 (m_teleportFlags & TeleportFlags.ViaLocation) != 0)
966 {
967 // Don't restrict gods, estate managers, or land owners to
968 // the TP point. This behaviour mimics agni.
969 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
970 land.LandData.UserLocation != Vector3.Zero &&
971 GodLevel < 200 &&
972 ((land.LandData.OwnerID != m_uuid &&
973 (!m_scene.Permissions.IsGod(m_uuid)) &&
974 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) || (m_teleportFlags & TeleportFlags.ViaLocation) != 0))
975 {
976 pos = land.LandData.UserLocation;
977 }
978 }
979
980 land.SendLandUpdateToClient(ControllingClient);
981 }
982
983 if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
984 {
985 Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
986
987 if (pos.X < 0)
988 {
989 emergencyPos.X = (int)Constants.RegionSize + pos.X;
990 if (!(pos.Y < 0))
991 emergencyPos.Y = pos.Y;
992 if (!(pos.Z < 0))
993 emergencyPos.Z = pos.Z;
994 }
995 if (pos.Y < 0)
996 {
997 emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
998 if (!(pos.X < 0))
999 emergencyPos.X = pos.X;
1000 if (!(pos.Z < 0))
1001 emergencyPos.Z = pos.Z;
1002 }
1003 if (pos.Z < 0)
1004 {
1005 emergencyPos.Z = 128;
1006 if (!(pos.Y < 0))
1007 emergencyPos.Y = pos.Y;
1008 if (!(pos.X < 0))
1009 emergencyPos.X = pos.X;
1010 }
1011 }
1012
873 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 1013 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
874 { 1014 {
875 m_log.WarnFormat( 1015 m_log.WarnFormat(
@@ -1002,16 +1142,21 @@ namespace OpenSim.Region.Framework.Scenes
1002 /// <summary> 1142 /// <summary>
1003 /// Removes physics plugin scene representation of this agent if it exists. 1143 /// Removes physics plugin scene representation of this agent if it exists.
1004 /// </summary> 1144 /// </summary>
1005 private void RemoveFromPhysicalScene() 1145 public void RemoveFromPhysicalScene()
1006 { 1146 {
1007 if (PhysicsActor != null) 1147 if (PhysicsActor != null)
1008 { 1148 {
1009 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1149 try
1010 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall; 1150 {
1011 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); 1151 m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
1012 m_physicsActor.UnSubscribeEvents(); 1152 m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
1013 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1153 m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1014 PhysicsActor = null; 1154 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
1155 m_physicsActor.UnSubscribeEvents();
1156 PhysicsActor = null;
1157 }
1158 catch
1159 { }
1015 } 1160 }
1016 } 1161 }
1017 1162
@@ -1022,15 +1167,18 @@ namespace OpenSim.Region.Framework.Scenes
1022 public void Teleport(Vector3 pos) 1167 public void Teleport(Vector3 pos)
1023 { 1168 {
1024 bool isFlying = false; 1169 bool isFlying = false;
1170
1025 if (m_physicsActor != null) 1171 if (m_physicsActor != null)
1026 isFlying = m_physicsActor.Flying; 1172 isFlying = m_physicsActor.Flying;
1027 1173
1028 RemoveFromPhysicalScene(); 1174 RemoveFromPhysicalScene();
1029 Velocity = Vector3.Zero; 1175 Velocity = Vector3.Zero;
1176 CheckLandingPoint(ref pos);
1030 AbsolutePosition = pos; 1177 AbsolutePosition = pos;
1031 AddToPhysicalScene(isFlying); 1178 AddToPhysicalScene(isFlying);
1032 1179
1033 SendTerseUpdateToAllClients(); 1180 SendTerseUpdateToAllClients();
1181
1034 } 1182 }
1035 1183
1036 public void TeleportWithMomentum(Vector3 pos) 1184 public void TeleportWithMomentum(Vector3 pos)
@@ -1040,6 +1188,7 @@ namespace OpenSim.Region.Framework.Scenes
1040 isFlying = m_physicsActor.Flying; 1188 isFlying = m_physicsActor.Flying;
1041 1189
1042 RemoveFromPhysicalScene(); 1190 RemoveFromPhysicalScene();
1191 CheckLandingPoint(ref pos);
1043 AbsolutePosition = pos; 1192 AbsolutePosition = pos;
1044 AddToPhysicalScene(isFlying); 1193 AddToPhysicalScene(isFlying);
1045 1194
@@ -1240,6 +1389,7 @@ namespace OpenSim.Region.Framework.Scenes
1240 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); 1389 m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
1241 1390
1242 m_pos = m_LastFinitePos; 1391 m_pos = m_LastFinitePos;
1392
1243 if (!m_pos.IsFinite()) 1393 if (!m_pos.IsFinite())
1244 { 1394 {
1245 m_pos.X = 127f; 1395 m_pos.X = 127f;
@@ -1309,7 +1459,6 @@ namespace OpenSim.Region.Framework.Scenes
1309 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback); 1459 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
1310 } 1460 }
1311 } 1461 }
1312
1313 lock (scriptedcontrols) 1462 lock (scriptedcontrols)
1314 { 1463 {
1315 if (scriptedcontrols.Count > 0) 1464 if (scriptedcontrols.Count > 0)
@@ -1324,6 +1473,9 @@ namespace OpenSim.Region.Framework.Scenes
1324 1473
1325 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0) 1474 if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
1326 { 1475 {
1476 m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
1477 Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
1478
1327 // TODO: This doesn't prevent the user from walking yet. 1479 // TODO: This doesn't prevent the user from walking yet.
1328 // Setting parent ID would fix this, if we knew what value 1480 // Setting parent ID would fix this, if we knew what value
1329 // to use. Or we could add a m_isSitting variable. 1481 // to use. Or we could add a m_isSitting variable.
@@ -1378,6 +1530,20 @@ namespace OpenSim.Region.Framework.Scenes
1378 if (actor.Flying != oldflying) 1530 if (actor.Flying != oldflying)
1379 update_movementflag = true; 1531 update_movementflag = true;
1380 1532
1533 if (m_animator.m_jumping) // add for jumping
1534 update_movementflag = true;
1535
1536 if (q != m_bodyRot)
1537 {
1538 m_bodyRot = q;
1539 update_rotation = true;
1540 }
1541
1542 //guilty until proven innocent..
1543 bool Nudging = true;
1544 //Basically, if there is at least one non-nudge control then we don't need
1545 //to worry about stopping the avatar
1546
1381 if (m_parentID == 0) 1547 if (m_parentID == 0)
1382 { 1548 {
1383 bool bAllowUpdateMoveToPosition = false; 1549 bool bAllowUpdateMoveToPosition = false;
@@ -1391,10 +1557,12 @@ namespace OpenSim.Region.Framework.Scenes
1391 else 1557 else
1392 dirVectors = Dir_Vectors; 1558 dirVectors = Dir_Vectors;
1393 1559
1394 // The fact that m_movementflag is a byte needs to be fixed 1560 bool[] isNudge = GetDirectionIsNudge();
1395 // it really should be a uint 1561
1396 // A DIR_CONTROL_FLAG occurs when the user is trying to move in a particular direction. 1562
1397 uint nudgehack = 250; 1563
1564
1565
1398 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS) 1566 foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
1399 { 1567 {
1400 if (((uint)flags & (uint)DCF) != 0) 1568 if (((uint)flags & (uint)DCF) != 0)
@@ -1404,19 +1572,18 @@ namespace OpenSim.Region.Framework.Scenes
1404 try 1572 try
1405 { 1573 {
1406 agent_control_v3 += dirVectors[i]; 1574 agent_control_v3 += dirVectors[i];
1407 //m_log.DebugFormat("[Motion]: {0}, {1}",i, dirVectors[i]); 1575 if (isNudge[i] == false)
1576 {
1577 Nudging = false;
1578 }
1408 } 1579 }
1409 catch (IndexOutOfRangeException) 1580 catch (IndexOutOfRangeException)
1410 { 1581 {
1411 // Why did I get this? 1582 // Why did I get this?
1412 } 1583 }
1413 1584
1414 if ((m_movementflag & (byte)(uint)DCF) == 0) 1585 if ((m_movementflag & (uint)DCF) == 0)
1415 { 1586 {
1416 if (DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1417 {
1418 m_movementflag |= (byte)nudgehack;
1419 }
1420 1587
1421// m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with {1}", Name, DCF); 1588// m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with {1}", Name, DCF);
1422 m_movementflag += (byte)(uint)DCF; 1589 m_movementflag += (byte)(uint)DCF;
@@ -1425,22 +1592,10 @@ namespace OpenSim.Region.Framework.Scenes
1425 } 1592 }
1426 else 1593 else
1427 { 1594 {
1428 if ((m_movementflag & (byte)(uint)DCF) != 0 || 1595 if ((m_movementflag & (uint)DCF) != 0)
1429 ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1430 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1431 ) // This or is for Nudge forward
1432 { 1596 {
1433// m_log.DebugFormat("[SCENE PRESENCE]: Updating m_movementflag for {0} with lack of {1}", Name, DCF); 1597 m_movementflag -= (byte)(uint)DCF;
1434 m_movementflag -= ((byte)(uint)DCF);
1435 update_movementflag = true; 1598 update_movementflag = true;
1436
1437 /*
1438 if ((DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD_NUDGE || DCF == Dir_ControlFlags.DIR_CONTROL_FLAG_BACKWARD_NUDGE)
1439 && ((m_movementflag & (byte)nudgehack) == nudgehack))
1440 {
1441 m_log.Debug("Removed Hack flag");
1442 }
1443 */
1444 } 1599 }
1445 else 1600 else
1446 { 1601 {
@@ -1450,19 +1605,128 @@ namespace OpenSim.Region.Framework.Scenes
1450 1605
1451 i++; 1606 i++;
1452 } 1607 }
1453
1454 if (MovingToTarget) 1608 if (MovingToTarget)
1455 { 1609 {
1456 // If the user has pressed a key then we want to cancel any move to target. 1610 m_moveToPositionTarget = Vector3.Zero;
1457 if (DCFlagKeyPressed) 1611 m_moveToPositionInProgress = false;
1612 update_movementflag = true;
1613 bAllowUpdateMoveToPosition = false;
1614 }
1615
1616 if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
1617 {
1618/*
1619 bool twoD = false;
1620 bool there = false;
1621 if (Animator != null)
1622 {
1623 switch (Animator.CurrentMovementAnimation)
1624 {
1625 case "STAND":
1626 case "WALK":
1627 case "RUN":
1628 case "CROUCH":
1629 case "CROUCHWALK":
1630 {
1631 twoD = true;
1632 }
1633 break;
1634 }
1635 }
1636
1637 if (twoD)
1638 {
1639*/
1640 Vector3 abspos = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, 0.0f);
1641 Vector3 tgt = new Vector3(m_moveToPositionTarget.X, m_moveToPositionTarget.Y, 0.0f);
1642/* if (Util.GetDistanceTo(abspos, tgt) <= 0.5f) there = true;
1643 }
1644 else
1645 {
1646 if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f) there = true;
1647 }
1648*/
1649 //Check the error term of the current position in relation to the target position
1650// if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
1651// if (there)
1652 if (Util.GetDistanceTo(abspos, tgt) <= 0.5f)
1458 { 1653 {
1459 ResetMoveToTarget(); 1654 ResetMoveToTarget();
1460 update_movementflag = true; 1655 update_movementflag = true;
1461 } 1656 }
1462 else if (bAllowUpdateMoveToPosition) 1657 else if (bAllowUpdateMoveToPosition)
1463 { 1658 {
1464 if (HandleMoveToTargetUpdate(ref agent_control_v3)) 1659 try
1465 update_movementflag = true; 1660 {
1661 // move avatar in 2D at one meter/second towards target, in avatar coordinate frame.
1662 // This movement vector gets added to the velocity through AddNewMovement().
1663 // Theoretically we might need a more complex PID approach here if other
1664 // unknown forces are acting on the avatar and we need to adaptively respond
1665 // to such forces, but the following simple approach seems to works fine.
1666 Vector3 LocalVectorToTarget3D =
1667// (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
1668 (tgt - abspos)
1669 * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
1670 // Ignore z component of vector
1671 Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
1672 LocalVectorToTarget2D.Normalize();
1673
1674 //We're not nudging
1675 Nudging = false;
1676 agent_control_v3 += LocalVectorToTarget2D;
1677
1678 // update avatar movement flags. the avatar coordinate system is as follows:
1679 //
1680 // +X (forward)
1681 //
1682 // ^
1683 // |
1684 // |
1685 // |
1686 // |
1687 // (left) +Y <--------o--------> -Y
1688 // avatar
1689 // |
1690 // |
1691 // |
1692 // |
1693 // v
1694 // -X
1695 //
1696
1697 // based on the above avatar coordinate system, classify the movement into
1698 // one of left/right/back/forward.
1699 if (LocalVectorToTarget2D.Y > 0)//MoveLeft
1700 {
1701 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
1702 //AgentControlFlags
1703 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
1704 update_movementflag = true;
1705 }
1706 else if (LocalVectorToTarget2D.Y < 0) //MoveRight
1707 {
1708 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
1709 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
1710 update_movementflag = true;
1711 }
1712 if (LocalVectorToTarget2D.X < 0) //MoveBack
1713 {
1714 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
1715 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
1716 update_movementflag = true;
1717 }
1718 else if (LocalVectorToTarget2D.X > 0) //Move Forward
1719 {
1720 m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
1721 AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
1722 update_movementflag = true;
1723 }
1724 }
1725 catch (Exception e)
1726 {
1727 //Avoid system crash, can be slower but...
1728 m_log.DebugFormat("Crash! {0}", e.ToString());
1729 }
1466 } 1730 }
1467 } 1731 }
1468 } 1732 }
@@ -1499,7 +1763,9 @@ namespace OpenSim.Region.Framework.Scenes
1499// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}", 1763// "[SCENE PRESENCE]: In {0} adding velocity of {1} to {2}, umf = {3}, ur = {4}",
1500// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation); 1764// m_scene.RegionInfo.RegionName, agent_control_v3, Name, update_movementflag, update_rotation);
1501 1765
1502 AddNewMovement(agent_control_v3); 1766 AddNewMovement(agent_control_v3, q, Nudging);
1767
1768
1503 } 1769 }
1504// else 1770// else
1505// { 1771// {
@@ -1515,6 +1781,9 @@ namespace OpenSim.Region.Framework.Scenes
1515 Animator.UpdateMovementAnimations(); 1781 Animator.UpdateMovementAnimations();
1516 } 1782 }
1517 1783
1784 if (update_movementflag && !SitGround)
1785 Animator.UpdateMovementAnimations();
1786
1518 m_scene.EventManager.TriggerOnClientMovement(this); 1787 m_scene.EventManager.TriggerOnClientMovement(this);
1519 1788
1520 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 1789 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
@@ -1531,14 +1800,18 @@ namespace OpenSim.Region.Framework.Scenes
1531 public bool HandleMoveToTargetUpdate(ref Vector3 agent_control_v3) 1800 public bool HandleMoveToTargetUpdate(ref Vector3 agent_control_v3)
1532 { 1801 {
1533// m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name); 1802// m_log.DebugFormat("[SCENE PRESENCE]: Called HandleMoveToTargetUpdate() for {0}", Name);
1534
1535 bool updated = false; 1803 bool updated = false;
1536 1804
1537// m_log.DebugFormat( 1805 public void StopMoveToPosition()
1538// "[SCENE PRESENCE]: bAllowUpdateMoveToPosition {0}, m_moveToPositionInProgress {1}, m_autopilotMoving {2}", 1806 {
1539// allowUpdate, m_moveToPositionInProgress, m_autopilotMoving); 1807 m_moveToPositionTarget = Vector3.Zero;
1808 m_moveToPositionInProgress = false;
1809 }
1540 1810
1541 if (!m_autopilotMoving) 1811 public void DoMoveToPosition(Object sender, string method, List<String> args)
1812 {
1813//Console.WriteLine("SP:DoMoveToPosition");
1814 try
1542 { 1815 {
1543 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget); 1816 double distanceToTarget = Util.GetDistanceTo(AbsolutePosition, MoveToPositionTarget);
1544// m_log.DebugFormat( 1817// m_log.DebugFormat(
@@ -1644,7 +1917,7 @@ namespace OpenSim.Region.Framework.Scenes
1644 m_log.DebugFormat("Crash! {0}", e.ToString()); 1917 m_log.DebugFormat("Crash! {0}", e.ToString());
1645 } 1918 }
1646 } 1919 }
1647 } 1920 }
1648 1921
1649 return updated; 1922 return updated;
1650 } 1923 }
@@ -1736,7 +2009,7 @@ namespace OpenSim.Region.Framework.Scenes
1736 Velocity = Vector3.Zero; 2009 Velocity = Vector3.Zero;
1737 SendAvatarDataToAllAgents(); 2010 SendAvatarDataToAllAgents();
1738 2011
1739 //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); 2012 HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
1740 } 2013 }
1741 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false); 2014 //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
1742 m_requestedSitTargetUUID = UUID.Zero; 2015 m_requestedSitTargetUUID = UUID.Zero;
@@ -1773,25 +2046,22 @@ namespace OpenSim.Region.Framework.Scenes
1773 2046
1774 if (m_parentID != 0) 2047 if (m_parentID != 0)
1775 { 2048 {
1776 m_log.Debug("StandupCode Executed"); 2049 SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
1777 SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
1778 if (part != null) 2050 if (part != null)
1779 { 2051 {
2052 part.TaskInventory.LockItemsForRead(true);
1780 TaskInventoryDictionary taskIDict = part.TaskInventory; 2053 TaskInventoryDictionary taskIDict = part.TaskInventory;
1781 if (taskIDict != null) 2054 if (taskIDict != null)
1782 { 2055 {
1783 lock (taskIDict) 2056 foreach (UUID taskID in taskIDict.Keys)
1784 { 2057 {
1785 foreach (UUID taskID in taskIDict.Keys) 2058 UnRegisterControlEventsToScript(LocalId, taskID);
1786 { 2059 taskIDict[taskID].PermsMask &= ~(
1787 UnRegisterControlEventsToScript(LocalId, taskID); 2060 2048 | //PERMISSION_CONTROL_CAMERA
1788 taskIDict[taskID].PermsMask &= ~( 2061 4); // PERMISSION_TAKE_CONTROLS
1789 2048 | //PERMISSION_CONTROL_CAMERA
1790 4); // PERMISSION_TAKE_CONTROLS
1791 }
1792 } 2062 }
1793
1794 } 2063 }
2064 part.TaskInventory.LockItemsForRead(false);
1795 // Reset sit target. 2065 // Reset sit target.
1796 if (part.GetAvatarOnSitTarget() == UUID) 2066 if (part.GetAvatarOnSitTarget() == UUID)
1797 part.SitTargetAvatar = UUID.Zero; 2067 part.SitTargetAvatar = UUID.Zero;
@@ -1800,20 +2070,58 @@ namespace OpenSim.Region.Framework.Scenes
1800 m_parentPosition = part.GetWorldPosition(); 2070 m_parentPosition = part.GetWorldPosition();
1801 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 2071 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1802 } 2072 }
2073 // part.GetWorldRotation() is the rotation of the object being sat on
2074 // Rotation is the sittiing Av's rotation
2075
2076 Quaternion partRot;
2077// if (part.LinkNum == 1)
2078// { // Root prim of linkset
2079// partRot = part.ParentGroup.RootPart.RotationOffset;
2080// }
2081// else
2082// { // single or child prim
2083
2084// }
2085 if (part == null) //CW: Part may be gone. llDie() for example.
2086 {
2087 partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
2088 }
2089 else
2090 {
2091 partRot = part.GetWorldRotation();
2092 }
2093
2094 Quaternion partIRot = Quaternion.Inverse(partRot);
1803 2095
2096 Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
2097 Vector3 avStandUp = new Vector3(0.3f, 0f, 0f) * avatarRot; // 0.3M infront of av
2098
2099
1804 if (m_physicsActor == null) 2100 if (m_physicsActor == null)
1805 { 2101 {
1806 AddToPhysicalScene(false); 2102 AddToPhysicalScene(false);
1807 } 2103 }
1808 2104 //CW: If the part isn't null then we can set the current position
1809 m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight); 2105 if (part != null)
1810 m_parentPosition = Vector3.Zero; 2106 {
1811 2107 Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
1812 m_parentID = 0; 2108 AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
2109 part.IsOccupied = false;
2110 part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
2111 }
2112 else
2113 {
2114 //CW: Since the part doesn't exist, a coarse standup position isn't an issue
2115 AbsolutePosition = m_lastWorldPosition;
2116 }
2117
2118 m_parentPosition = Vector3.Zero;
2119 m_parentID = 0;
2120 m_linkedPrim = UUID.Zero;
2121 m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
1813 SendAvatarDataToAllAgents(); 2122 SendAvatarDataToAllAgents();
1814 m_requestedSitTargetID = 0; 2123 m_requestedSitTargetID = 0;
1815 } 2124 }
1816
1817 Animator.TrySetMovementAnimation("STAND"); 2125 Animator.TrySetMovementAnimation("STAND");
1818 } 2126 }
1819 2127
@@ -1844,13 +2152,9 @@ namespace OpenSim.Region.Framework.Scenes
1844 Vector3 avSitOffSet = part.SitTargetPosition; 2152 Vector3 avSitOffSet = part.SitTargetPosition;
1845 Quaternion avSitOrientation = part.SitTargetOrientation; 2153 Quaternion avSitOrientation = part.SitTargetOrientation;
1846 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2154 UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
1847 2155 bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
1848 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero)); 2156 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
1849 bool SitTargetisSet = 2157 if (SitTargetisSet && !SitTargetOccupied)
1850 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
1851 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
1852
1853 if (SitTargetisSet && SitTargetUnOccupied)
1854 { 2158 {
1855 //switch the target to this prim 2159 //switch the target to this prim
1856 return part; 2160 return part;
@@ -1864,85 +2168,168 @@ namespace OpenSim.Region.Framework.Scenes
1864 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation) 2168 private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
1865 { 2169 {
1866 bool autopilot = true; 2170 bool autopilot = true;
2171 Vector3 autopilotTarget = new Vector3();
2172 Quaternion sitOrientation = Quaternion.Identity;
1867 Vector3 pos = new Vector3(); 2173 Vector3 pos = new Vector3();
1868 Quaternion sitOrientation = pSitOrientation;
1869 Vector3 cameraEyeOffset = Vector3.Zero; 2174 Vector3 cameraEyeOffset = Vector3.Zero;
1870 Vector3 cameraAtOffset = Vector3.Zero; 2175 Vector3 cameraAtOffset = Vector3.Zero;
1871 bool forceMouselook = false; 2176 bool forceMouselook = false;
1872 2177
1873 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID); 2178 //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
1874 SceneObjectPart part = FindNextAvailableSitTarget(targetID); 2179 SceneObjectPart part = FindNextAvailableSitTarget(targetID);
1875 if (part != null) 2180 if (part == null) return;
2181
2182 // TODO: determine position to sit at based on scene geometry; don't trust offset from client
2183 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
2184
2185 // part is the prim to sit on
2186 // offset is the world-ref vector distance from that prim center to the click-spot
2187 // UUID is the UUID of the Avatar doing the clicking
2188
2189 m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
2190
2191 // Is a sit target available?
2192 Vector3 avSitOffSet = part.SitTargetPosition;
2193 Quaternion avSitOrientation = part.SitTargetOrientation;
2194
2195 bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
2196 // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
2197 Quaternion partRot;
2198// if (part.LinkNum == 1)
2199// { // Root prim of linkset
2200// partRot = part.ParentGroup.RootPart.RotationOffset;
2201// }
2202// else
2203// { // single or child prim
2204 partRot = part.GetWorldRotation();
2205// }
2206 Quaternion partIRot = Quaternion.Inverse(partRot);
2207//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
2208 // Sit analysis rewritten by KF 091125
2209 if (SitTargetisSet) // scipted sit
1876 { 2210 {
1877 // TODO: determine position to sit at based on scene geometry; don't trust offset from client 2211 if (!part.IsOccupied)
1878 // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it 2212 {
1879 2213//Console.WriteLine("Scripted, unoccupied");
1880 // Is a sit target available? 2214 part.SitTargetAvatar = UUID; // set that Av will be on it
1881 Vector3 avSitOffSet = part.SitTargetPosition; 2215 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
1882 Quaternion avSitOrientation = part.SitTargetOrientation; 2216
1883 UUID avOnTargetAlready = part.GetAvatarOnSitTarget(); 2217 Quaternion nrot = avSitOrientation;
1884 2218 if (!part.IsRoot)
1885 bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
1886 bool SitTargetisSet =
1887 (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f &&
1888 (
1889 avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 1f // Valid Zero Rotation quaternion
1890 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f && avSitOrientation.W == 0f // W-Z Mapping was invalid at one point
1891 || avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f && avSitOrientation.W == 0f // Invalid Quaternion
1892 )
1893 ));
1894
1895 if (SitTargetisSet && SitTargetUnOccupied)
1896 {
1897 part.SitTargetAvatar = UUID;
1898 offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z);
1899 sitOrientation = avSitOrientation;
1900 autopilot = false;
1901 }
1902 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1903
1904 pos = part.AbsolutePosition + offset;
1905 //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1)
1906 //{
1907 // offset = pos;
1908 //autopilot = false;
1909 //}
1910 if (m_physicsActor != null)
1911 {
1912 // If we're not using the client autopilot, we're immediately warping the avatar to the location
1913 // We can remove the physicsActor until they stand up.
1914 m_sitAvatarHeight = m_physicsActor.Size.Z;
1915
1916 if (autopilot)
1917 { 2219 {
1918 if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5) 2220 nrot = part.RotationOffset * avSitOrientation;
1919 {
1920 autopilot = false;
1921
1922 RemoveFromPhysicalScene();
1923 AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
1924 }
1925 } 2221 }
1926 else 2222 sitOrientation = nrot; // Change rotatione to the scripted one
2223 OffsetRotation = nrot;
2224 autopilot = false; // Jump direct to scripted llSitPos()
2225 }
2226 else
2227 {
2228//Console.WriteLine("Scripted, occupied");
2229 return;
2230 }
2231 }
2232 else // Not Scripted
2233 {
2234 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
2235 {
2236 // large prim & offset, ignore if other Avs sitting
2237// offset.Z -= 0.05f;
2238 m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
2239 autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
2240
2241//Console.WriteLine(" offset ={0}", offset);
2242//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
2243//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
2244
2245 }
2246 else // small offset
2247 {
2248//Console.WriteLine("Small offset");
2249 if (!part.IsOccupied)
2250 {
2251 m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
2252 autopilotTarget = part.AbsolutePosition;
2253//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
2254 }
2255 else return; // occupied small
2256 } // end large/small
2257 } // end Scripted/not
2258
2259 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
2260
2261 cameraAtOffset = part.GetCameraAtOffset();
2262 cameraEyeOffset = part.GetCameraEyeOffset();
2263 forceMouselook = part.GetForceMouselook();
2264 if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
2265 if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
2266
2267 if (m_physicsActor != null)
2268 {
2269 // If we're not using the client autopilot, we're immediately warping the avatar to the location
2270 // We can remove the physicsActor until they stand up.
2271 m_sitAvatarHeight = m_physicsActor.Size.Z;
2272 if (autopilot)
2273 { // its not a scripted sit
2274// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
2275 if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
1927 { 2276 {
2277 autopilot = false; // close enough
2278 m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2279 Not using the part's position because returning the AV to the last known standing
2280 position is likely to be more friendly, isn't it? */
1928 RemoveFromPhysicalScene(); 2281 RemoveFromPhysicalScene();
1929 } 2282 Velocity = Vector3.Zero;
2283 AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
2284 } // else the autopilot will get us close
2285 }
2286 else
2287 { // its a scripted sit
2288 m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
2289 I *am* using the part's position this time because we have no real idea how far away
2290 the avatar is from the sit target. */
2291 RemoveFromPhysicalScene();
2292 Velocity = Vector3.Zero;
1930 } 2293 }
1931
1932 cameraAtOffset = part.GetCameraAtOffset();
1933 cameraEyeOffset = part.GetCameraEyeOffset();
1934 forceMouselook = part.GetForceMouselook();
1935 } 2294 }
1936 2295 else return; // physactor is null!
1937 ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook); 2296
1938 m_requestedSitTargetUUID = targetID; 2297 Vector3 offsetr; // = offset * partIRot;
2298 // KF: In a linkset, offsetr needs to be relative to the group root! 091208
2299 // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
2300 // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
2301 // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
2302 //offsetr = offset * partIRot;
2303//
2304 // }
2305 // else
2306 // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
2307 // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
2308 // (offset * partRot);
2309 // }
2310
2311//Console.WriteLine(" ");
2312//Console.WriteLine("link number ={0}", part.LinkNum);
2313//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
2314//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
2315//Console.WriteLine("Click offst ={0}", offset);
2316//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
2317//Console.WriteLine("offsetr ={0}", offsetr);
2318//Console.WriteLine("Camera At ={0}", cameraAtOffset);
2319//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
2320
2321 //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
2322 ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
2323
2324 m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
1939 // This calls HandleAgentSit twice, once from here, and the client calls 2325 // This calls HandleAgentSit twice, once from here, and the client calls
1940 // HandleAgentSit itself after it gets to the location 2326 // HandleAgentSit itself after it gets to the location
1941 // It doesn't get to the location until we've moved them there though 2327 // It doesn't get to the location until we've moved them there though
1942 // which happens in HandleAgentSit :P 2328 // which happens in HandleAgentSit :P
1943 m_autopilotMoving = autopilot; 2329 m_autopilotMoving = autopilot;
1944 m_autoPilotTarget = pos; 2330 m_autoPilotTarget = autopilotTarget;
1945 m_sitAtAutoTarget = autopilot; 2331 m_sitAtAutoTarget = autopilot;
2332 m_initialSitTarget = autopilotTarget;
1946 if (!autopilot) 2333 if (!autopilot)
1947 HandleAgentSit(remoteClient, UUID); 2334 HandleAgentSit(remoteClient, UUID);
1948 } 2335 }
@@ -2207,47 +2594,130 @@ namespace OpenSim.Region.Framework.Scenes
2207 { 2594 {
2208 if (part != null) 2595 if (part != null)
2209 { 2596 {
2597//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
2210 if (part.GetAvatarOnSitTarget() == UUID) 2598 if (part.GetAvatarOnSitTarget() == UUID)
2211 { 2599 {
2600//Console.WriteLine("Scripted Sit");
2601 // Scripted sit
2212 Vector3 sitTargetPos = part.SitTargetPosition; 2602 Vector3 sitTargetPos = part.SitTargetPosition;
2213 Quaternion sitTargetOrient = part.SitTargetOrientation; 2603 Quaternion sitTargetOrient = part.SitTargetOrientation;
2214
2215 //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
2216 //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
2217
2218 //Quaternion result = (sitTargetOrient * vq) * nq;
2219
2220 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z); 2604 m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
2221 m_pos += SIT_TARGET_ADJUSTMENT; 2605 m_pos += SIT_TARGET_ADJUSTMENT;
2606 if (!part.IsRoot)
2607 {
2608 m_pos *= part.RotationOffset;
2609 }
2222 m_bodyRot = sitTargetOrient; 2610 m_bodyRot = sitTargetOrient;
2223 //Rotation = sitTargetOrient;
2224 m_parentPosition = part.AbsolutePosition; 2611 m_parentPosition = part.AbsolutePosition;
2225 2612 part.IsOccupied = true;
2226 //SendTerseUpdateToAllClients(); 2613 part.ParentGroup.AddAvatar(agentID);
2227 } 2614 }
2228 else 2615 else
2229 { 2616 {
2230 m_pos -= part.AbsolutePosition; 2617 // if m_avUnscriptedSitPos is zero then Av sits above center
2618 // Else Av sits at m_avUnscriptedSitPos
2619
2620 // Non-scripted sit by Kitto Flora 21Nov09
2621 // Calculate angle of line from prim to Av
2622 Quaternion partIRot;
2623// if (part.LinkNum == 1)
2624// { // Root prim of linkset
2625// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2626// }
2627// else
2628// { // single or child prim
2629 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2630// }
2631 Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
2632 float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
2633 float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
2634 if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
2635 if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
2636 float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
2637 // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
2638 // Av sits at world euler <0,0, z>, translated by part rotation
2639 m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
2640
2231 m_parentPosition = part.AbsolutePosition; 2641 m_parentPosition = part.AbsolutePosition;
2232 } 2642 part.IsOccupied = true;
2643 part.ParentGroup.AddAvatar(agentID);
2644 m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
2645 (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
2646 (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
2647 m_avUnscriptedSitPos; // adds click offset, if any
2648 //Set up raytrace to find top surface of prim
2649 Vector3 size = part.Scale;
2650 float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
2651 Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
2652 Vector3 down = new Vector3(0f, 0f, -1f);
2653//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
2654 m_scene.PhysicsScene.RaycastWorld(
2655 start, // Vector3 position,
2656 down, // Vector3 direction,
2657 mag, // float length,
2658 SitAltitudeCallback); // retMethod
2659 } // end scripted/not
2233 } 2660 }
2234 else 2661 else // no Av
2235 { 2662 {
2236 return; 2663 return;
2237 } 2664 }
2238 } 2665 }
2239 m_parentID = m_requestedSitTargetID;
2240 2666
2667 //We want our offsets to reference the root prim, not the child we may have sat on
2668 if (!part.IsRoot)
2669 {
2670 m_parentID = part.ParentGroup.RootPart.LocalId;
2671 m_pos += part.OffsetPosition;
2672 }
2673 else
2674 {
2675 m_parentID = m_requestedSitTargetID;
2676 }
2677
2678 m_linkedPrim = part.UUID;
2679 if (part.GetAvatarOnSitTarget() != UUID)
2680 {
2681 m_offsetRotation = m_offsetRotation / part.RotationOffset;
2682 }
2241 Velocity = Vector3.Zero; 2683 Velocity = Vector3.Zero;
2242 RemoveFromPhysicalScene(); 2684 RemoveFromPhysicalScene();
2243
2244 Animator.TrySetMovementAnimation(sitAnimation); 2685 Animator.TrySetMovementAnimation(sitAnimation);
2245 SendAvatarDataToAllAgents(); 2686 SendAvatarDataToAllAgents();
2246 // This may seem stupid, but Our Full updates don't send avatar rotation :P
2247 // So we're also sending a terse update (which has avatar rotation)
2248 // [Update] We do now.
2249 //SendTerseUpdateToAllClients(); 2687 //SendTerseUpdateToAllClients();
2250 } 2688 }
2689
2690 public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
2691 {
2692 // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
2693 // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
2694 if(hitYN)
2695 {
2696 // m_pos = Av offset from prim center to make look like on center
2697 // m_parentPosition = Actual center pos of prim
2698 // collisionPoint = spot on prim where we want to sit
2699 // collisionPoint.Z = global sit surface height
2700 SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
2701 Quaternion partIRot;
2702// if (part.LinkNum == 1)
2703/// { // Root prim of linkset
2704// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
2705// }
2706// else
2707// { // single or child prim
2708 partIRot = Quaternion.Inverse(part.GetWorldRotation());
2709// }
2710 if (m_initialSitTarget != null)
2711 {
2712 float offZ = collisionPoint.Z - m_initialSitTarget.Z;
2713 Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
2714 //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
2715 m_pos += offset;
2716 // ControllingClient.SendClearFollowCamProperties(part.UUID);
2717 }
2718
2719 }
2720 } // End SitAltitudeCallback KF.
2251 2721
2252 /// <summary> 2722 /// <summary>
2253 /// Event handler for the 'Always run' setting on the client 2723 /// Event handler for the 'Always run' setting on the client
@@ -2276,21 +2746,41 @@ namespace OpenSim.Region.Framework.Scenes
2276 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 2746 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2277 /// </summary> 2747 /// </summary>
2278 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param> 2748 /// <param name="vec">The vector in which to move. This is relative to the rotation argument</param>
2279 public void AddNewMovement(Vector3 vec) 2749 /// <param name="rotation">The direction in which this avatar should now face.
2750 public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
2280 { 2751 {
2752 if (m_isChildAgent)
2753 {
2754 // WHAT???
2755 m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent");
2756
2757 return;
2758 }
2759
2281 m_perfMonMS = Util.EnvironmentTickCount(); 2760 m_perfMonMS = Util.EnvironmentTickCount();
2282 2761
2283 Vector3 direc = vec * Rotation; 2762 Vector3 direc = vec * Rotation;
2284 direc.Normalize(); 2763 direc.Normalize();
2764 PhysicsActor actor = m_physicsActor;
2765
2766 if (actor.Flying != m_flyingOld) // add for fly velocity control
2767 {
2768 m_flyingOld = actor.Flying; // add for fly velocity control
2769 if (!actor.Flying) m_wasFlying = true; // add for fly velocity control
2770 }
2771
2772 if (m_physicsActor.IsColliding == true) m_wasFlying = false; // add for fly velocity control
2773
2774 if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
2285 2775
2286 direc *= 0.03f * 128f * m_speedModifier; 2776 direc *= 0.03f * 128f * m_speedModifier;
2287 2777
2288 PhysicsActor actor = m_physicsActor;
2289 if (actor != null) 2778 if (actor != null)
2290 { 2779 {
2291 if (actor.Flying) 2780 if (actor.Flying)
2292 { 2781 {
2293 direc *= 4.0f; 2782// rm speed mod direc *= 4.0f;
2783 direc *= 5.2f; // for speed mod
2294 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 2784 //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
2295 //bool colliding = (m_physicsActor.IsColliding==true); 2785 //bool colliding = (m_physicsActor.IsColliding==true);
2296 //if (controlland) 2786 //if (controlland)
@@ -2303,22 +2793,34 @@ namespace OpenSim.Region.Framework.Scenes
2303 // m_log.Info("[AGENT]: Stop FLying"); 2793 // m_log.Info("[AGENT]: Stop FLying");
2304 //} 2794 //}
2305 } 2795 }
2796 if (Animator.m_falling && m_wasFlying) // if falling from flying, disable motion add
2797 {
2798 direc *= 0.0f;
2799 }
2800 /* This jumping section removed to SPA
2306 else if (!actor.Flying && actor.IsColliding) 2801 else if (!actor.Flying && actor.IsColliding)
2307 { 2802 {
2308 if (direc.Z > 2.0f) 2803 if (direc.Z > 2.0f)
2309 { 2804 {
2310 direc.Z *= 3.0f; 2805 if(m_animator.m_animTickJump == -1)
2311 2806 {
2312 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2807 direc.Z *= 3.0f; // jump
2313 Animator.TrySetMovementAnimation("PREJUMP"); 2808 }
2314 Animator.TrySetMovementAnimation("JUMP"); 2809 else
2810 {
2811 direc.Z *= 0.1f; // prejump
2812 }
2813 / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
2814 Animator.TrySetMovementAnimation("PREJUMP");
2815 Animator.TrySetMovementAnimation("JUMP");
2816 * /
2315 } 2817 }
2316 } 2818 } */
2317 } 2819 }
2318 2820
2319 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2821 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2320 m_forceToApply = direc; 2822 m_forceToApply = direc;
2321 2823 m_isNudging = Nudging;
2322 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2824 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2323 } 2825 }
2324 2826
@@ -2367,6 +2869,9 @@ namespace OpenSim.Region.Framework.Scenes
2367 2869
2368 CheckForSignificantMovement(); // sends update to the modules. 2870 CheckForSignificantMovement(); // sends update to the modules.
2369 } 2871 }
2872
2873 //Sending prim updates AFTER the avatar terse updates are sent
2874 SendPrimUpdates();
2370 } 2875 }
2371 2876
2372 #endregion 2877 #endregion
@@ -3172,6 +3677,7 @@ namespace OpenSim.Region.Framework.Scenes
3172 m_callbackURI = cAgent.CallbackURI; 3677 m_callbackURI = cAgent.CallbackURI;
3173 3678
3174 m_pos = cAgent.Position; 3679 m_pos = cAgent.Position;
3680
3175 m_velocity = cAgent.Velocity; 3681 m_velocity = cAgent.Velocity;
3176 m_CameraCenter = cAgent.Center; 3682 m_CameraCenter = cAgent.Center;
3177 m_CameraAtAxis = cAgent.AtAxis; 3683 m_CameraAtAxis = cAgent.AtAxis;
@@ -3260,17 +3766,45 @@ namespace OpenSim.Region.Framework.Scenes
3260 /// </summary> 3766 /// </summary>
3261 public override void UpdateMovement() 3767 public override void UpdateMovement()
3262 { 3768 {
3263 if (m_forceToApply.HasValue) 3769 if (Animator!=null) // add for jumping
3264 { 3770 { // add for jumping
3265 Vector3 force = m_forceToApply.Value; 3771 // if (!m_animator.m_jumping) // add for jumping
3772 // { // add for jumping
3266 3773
3267 m_updateflag = true; 3774 if (m_forceToApply.HasValue) // this section realigned
3268 3775 {
3269 Velocity = force;
3270 3776
3271 m_forceToApply = null; 3777 Vector3 force = m_forceToApply.Value;
3272 } 3778 m_updateflag = true;
3273 } 3779if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3780 Velocity = force;
3781//Console.WriteLine("UM1 {0}", Velocity);
3782 m_forceToApply = null;
3783 }
3784 else
3785 {
3786 if (m_isNudging)
3787 {
3788 Vector3 force = Vector3.Zero;
3789
3790 m_updateflag = true;
3791if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3792 Velocity = force;
3793//Console.WriteLine("UM2 {0}", Velocity);
3794 m_isNudging = false;
3795 m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
3796 }
3797 else // add for jumping
3798 { // add for jumping
3799 Vector3 force = Vector3.Zero; // add for jumping
3800if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
3801//Console.WriteLine("UM3 {0}", Velocity);
3802 Velocity = force; // add for jumping
3803 }
3804 }
3805 // } // end realign
3806 } // add for jumping
3807 } // add for jumping
3274 3808
3275 /// <summary> 3809 /// <summary>
3276 /// Adds a physical representation of the avatar to the Physics plugin 3810 /// Adds a physical representation of the avatar to the Physics plugin
@@ -3284,10 +3818,8 @@ namespace OpenSim.Region.Framework.Scenes
3284 3818
3285 Vector3 pVec = AbsolutePosition; 3819 Vector3 pVec = AbsolutePosition;
3286 3820
3287 // Old bug where the height was in centimeters instead of meters 3821 m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
3288 m_physicsActor = scene.AddAvatar(LocalId, Firstname + "." + Lastname, pVec,
3289 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying); 3822 new Vector3(0f, 0f, m_appearance.AvatarHeight), isFlying);
3290
3291 scene.AddPhysicsActorTaint(m_physicsActor); 3823 scene.AddPhysicsActorTaint(m_physicsActor);
3292 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3824 //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3293 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3825 m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
@@ -3313,18 +3845,29 @@ namespace OpenSim.Region.Framework.Scenes
3313 { 3845 {
3314 if (e == null) 3846 if (e == null)
3315 return; 3847 return;
3316 3848
3317 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) 3849 // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3318 // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
3319 // as of this comment the interval is set in AddToPhysicalScene 3850 // as of this comment the interval is set in AddToPhysicalScene
3320 if (Animator!=null) 3851 if (Animator!=null)
3321 Animator.UpdateMovementAnimations(); 3852 {
3853 if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
3854 { // else its will lock out other animation changes, like ground sit.
3855 Animator.UpdateMovementAnimations();
3856 m_updateCount--;
3857 }
3858 }
3322 3859
3323 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3860 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3324 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3861 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3325 3862
3326 CollisionPlane = Vector4.UnitW; 3863 CollisionPlane = Vector4.UnitW;
3327 3864
3865 if (m_lastColCount != coldata.Count)
3866 {
3867 m_updateCount = UPDATE_COUNT;
3868 m_lastColCount = coldata.Count;
3869 }
3870
3328 if (coldata.Count != 0 && Animator != null) 3871 if (coldata.Count != 0 && Animator != null)
3329 { 3872 {
3330 switch (Animator.CurrentMovementAnimation) 3873 switch (Animator.CurrentMovementAnimation)
@@ -3354,6 +3897,148 @@ namespace OpenSim.Region.Framework.Scenes
3354 } 3897 }
3355 } 3898 }
3356 3899
3900 List<uint> thisHitColliders = new List<uint>();
3901 List<uint> endedColliders = new List<uint>();
3902 List<uint> startedColliders = new List<uint>();
3903
3904 foreach (uint localid in coldata.Keys)
3905 {
3906 thisHitColliders.Add(localid);
3907 if (!m_lastColliders.Contains(localid))
3908 {
3909 startedColliders.Add(localid);
3910 }
3911 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3912 }
3913
3914 // calculate things that ended colliding
3915 foreach (uint localID in m_lastColliders)
3916 {
3917 if (!thisHitColliders.Contains(localID))
3918 {
3919 endedColliders.Add(localID);
3920 }
3921 }
3922 //add the items that started colliding this time to the last colliders list.
3923 foreach (uint localID in startedColliders)
3924 {
3925 m_lastColliders.Add(localID);
3926 }
3927 // remove things that ended colliding from the last colliders list
3928 foreach (uint localID in endedColliders)
3929 {
3930 m_lastColliders.Remove(localID);
3931 }
3932
3933 // do event notification
3934 if (startedColliders.Count > 0)
3935 {
3936 ColliderArgs StartCollidingMessage = new ColliderArgs();
3937 List<DetectedObject> colliding = new List<DetectedObject>();
3938 foreach (uint localId in startedColliders)
3939 {
3940 if (localId == 0)
3941 continue;
3942
3943 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3944 string data = "";
3945 if (obj != null)
3946 {
3947 DetectedObject detobj = new DetectedObject();
3948 detobj.keyUUID = obj.UUID;
3949 detobj.nameStr = obj.Name;
3950 detobj.ownerUUID = obj.OwnerID;
3951 detobj.posVector = obj.AbsolutePosition;
3952 detobj.rotQuat = obj.GetWorldRotation();
3953 detobj.velVector = obj.Velocity;
3954 detobj.colliderType = 0;
3955 detobj.groupUUID = obj.GroupID;
3956 colliding.Add(detobj);
3957 }
3958 }
3959
3960 if (colliding.Count > 0)
3961 {
3962 StartCollidingMessage.Colliders = colliding;
3963
3964 foreach (SceneObjectGroup att in Attachments)
3965 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
3966 }
3967 }
3968
3969 if (endedColliders.Count > 0)
3970 {
3971 ColliderArgs EndCollidingMessage = new ColliderArgs();
3972 List<DetectedObject> colliding = new List<DetectedObject>();
3973 foreach (uint localId in endedColliders)
3974 {
3975 if (localId == 0)
3976 continue;
3977
3978 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
3979 string data = "";
3980 if (obj != null)
3981 {
3982 DetectedObject detobj = new DetectedObject();
3983 detobj.keyUUID = obj.UUID;
3984 detobj.nameStr = obj.Name;
3985 detobj.ownerUUID = obj.OwnerID;
3986 detobj.posVector = obj.AbsolutePosition;
3987 detobj.rotQuat = obj.GetWorldRotation();
3988 detobj.velVector = obj.Velocity;
3989 detobj.colliderType = 0;
3990 detobj.groupUUID = obj.GroupID;
3991 colliding.Add(detobj);
3992 }
3993 }
3994
3995 if (colliding.Count > 0)
3996 {
3997 EndCollidingMessage.Colliders = colliding;
3998
3999 foreach (SceneObjectGroup att in Attachments)
4000 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4001 }
4002 }
4003
4004 if (thisHitColliders.Count > 0)
4005 {
4006 ColliderArgs CollidingMessage = new ColliderArgs();
4007 List<DetectedObject> colliding = new List<DetectedObject>();
4008 foreach (uint localId in thisHitColliders)
4009 {
4010 if (localId == 0)
4011 continue;
4012
4013 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4014 string data = "";
4015 if (obj != null)
4016 {
4017 DetectedObject detobj = new DetectedObject();
4018 detobj.keyUUID = obj.UUID;
4019 detobj.nameStr = obj.Name;
4020 detobj.ownerUUID = obj.OwnerID;
4021 detobj.posVector = obj.AbsolutePosition;
4022 detobj.rotQuat = obj.GetWorldRotation();
4023 detobj.velVector = obj.Velocity;
4024 detobj.colliderType = 0;
4025 detobj.groupUUID = obj.GroupID;
4026 colliding.Add(detobj);
4027 }
4028 }
4029
4030 if (colliding.Count > 0)
4031 {
4032 CollidingMessage.Colliders = colliding;
4033
4034 lock (m_attachments)
4035 {
4036 foreach (SceneObjectGroup att in m_attachments)
4037 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4038 }
4039 }
4040 }
4041
3357 if (m_invulnerable) 4042 if (m_invulnerable)
3358 return; 4043 return;
3359 4044
@@ -3426,6 +4111,10 @@ namespace OpenSim.Region.Framework.Scenes
3426 { 4111 {
3427 lock (m_attachments) 4112 lock (m_attachments)
3428 { 4113 {
4114 // This may be true when the attachment comes back
4115 // from serialization after login. Clear it.
4116 gobj.IsDeleted = false;
4117
3429 m_attachments.Add(gobj); 4118 m_attachments.Add(gobj);
3430 } 4119 }
3431 } 4120 }
@@ -3780,6 +4469,103 @@ namespace OpenSim.Region.Framework.Scenes
3780 return flags; 4469 return flags;
3781 } 4470 }
3782 4471
4472 /// <summary>
4473 /// RezAttachments. This should only be called upon login on the first region.
4474 /// Attachment rezzings on crossings and TPs are done in a different way.
4475 /// </summary>
4476 public void RezAttachments()
4477 {
4478 if (null == m_appearance)
4479 {
4480 m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID);
4481 return;
4482 }
4483
4484 XmlDocument doc = new XmlDocument();
4485 string stateData = String.Empty;
4486
4487 IAttachmentsService attServ = m_scene.RequestModuleInterface<IAttachmentsService>();
4488 if (attServ != null)
4489 {
4490 m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
4491 stateData = attServ.Get(ControllingClient.AgentId.ToString());
4492 if (stateData != String.Empty)
4493 {
4494 try
4495 {
4496 doc.LoadXml(stateData);
4497 }
4498 catch { }
4499 }
4500 }
4501
4502 Dictionary<UUID, string> itemData = new Dictionary<UUID, string>();
4503
4504 XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
4505 if (nodes.Count > 0)
4506 {
4507 foreach (XmlNode n in nodes)
4508 {
4509 XmlElement elem = (XmlElement)n;
4510 string itemID = elem.GetAttribute("ItemID");
4511 string xml = elem.InnerXml;
4512
4513 itemData[new UUID(itemID)] = xml;
4514 }
4515 }
4516
4517 List<AvatarAttachment> attachments = m_appearance.GetAttachments();
4518 foreach (AvatarAttachment attach in attachments)
4519 {
4520 if (m_isDeleted)
4521 return;
4522
4523 int p = attach.AttachPoint;
4524 UUID itemID = attach.ItemID;
4525
4526 //UUID assetID = attach.AssetID;
4527 // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down
4528 // But they're not used anyway, the item is being looked up for now, so let's proceed.
4529 //if (UUID.Zero == assetID)
4530 //{
4531 // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID);
4532 // continue;
4533 //}
4534
4535 try
4536 {
4537 string xmlData;
4538 XmlDocument d = new XmlDocument();
4539 UUID asset;
4540 if (itemData.TryGetValue(itemID, out xmlData))
4541 {
4542 d.LoadXml(xmlData);
4543 m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
4544
4545 // Rez from inventory
4546 asset
4547 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
4548
4549 }
4550 else
4551 {
4552 // Rez from inventory (with a null doc to let
4553 // CHANGED_OWNER happen)
4554 asset
4555 = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
4556 }
4557
4558 m_log.InfoFormat(
4559 "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}",
4560 p, itemID, asset);
4561 }
4562 catch (Exception e)
4563 {
4564 m_log.ErrorFormat("[ATTACHMENT]: Unable to rez attachment: {0}{1}", e.Message, e.StackTrace);
4565 }
4566 }
4567 }
4568
3783 private void ReprioritizeUpdates() 4569 private void ReprioritizeUpdates()
3784 { 4570 {
3785 if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time) 4571 if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time)
@@ -3804,5 +4590,62 @@ namespace OpenSim.Region.Framework.Scenes
3804 m_reprioritization_called = false; 4590 m_reprioritization_called = false;
3805 } 4591 }
3806 } 4592 }
4593
4594 private Vector3 Quat2Euler(Quaternion rot){
4595 float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
4596 (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
4597 float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
4598 float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
4599 (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
4600 return(new Vector3(x,y,z));
4601 }
4602
4603 public void SaveChangedAttachments()
4604 {
4605 // Need to copy this list because DetachToInventoryPrep mods it
4606 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(Attachments.ToArray());
4607
4608 IAttachmentsModule attachmentsModule = m_scene.AttachmentsModule;
4609 if (attachmentsModule != null)
4610 {
4611 foreach (SceneObjectGroup grp in attachments)
4612 {
4613 if (grp.HasGroupChanged) // Resizer scripts?
4614 {
4615 grp.RootPart.IsAttachment = false;
4616 grp.AbsolutePosition = grp.RootPart.AttachedPos;
4617// grp.DetachToInventoryPrep();
4618 attachmentsModule.UpdateKnownItem(ControllingClient,
4619 grp, grp.GetFromItemID(), grp.OwnerID);
4620 grp.RootPart.IsAttachment = true;
4621 }
4622 }
4623 }
4624 }
4625
4626 private void CheckLandingPoint(ref Vector3 pos)
4627 {
4628 // Never constrain lures
4629 if ((TeleportFlags & TeleportFlags.ViaLure) != 0)
4630 return;
4631
4632 if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport)
4633 return;
4634
4635 ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
4636
4637 if (land.LandData.LandingType == (byte)LandingType.LandingPoint &&
4638 land.LandData.UserLocation != Vector3.Zero &&
4639 land.LandData.OwnerID != m_uuid &&
4640 (!m_scene.Permissions.IsGod(m_uuid)) &&
4641 (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)))
4642 {
4643 float curr = Vector3.Distance(AbsolutePosition, pos);
4644 if (Vector3.Distance(land.LandData.UserLocation, pos) < curr)
4645 pos = land.LandData.UserLocation;
4646 else
4647 ControllingClient.SendAlertMessage("Can't teleport closer to destination");
4648 }
4649 }
3807 } 4650 }
3808} \ No newline at end of file 4651} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
index e2ea830..501487a 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 != null && 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 e06a222..11dad6c 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -346,6 +346,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
346 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 346 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
347 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 347 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
348 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 348 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
349
350 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
349 #endregion 351 #endregion
350 352
351 #region TaskInventoryXmlProcessors initialization 353 #region TaskInventoryXmlProcessors initialization
@@ -735,6 +737,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
735 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 737 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
736 } 738 }
737 739
740 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
741 {
742 obj.Buoyancy = (int)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
743 }
744
738 #endregion 745 #endregion
739 746
740 #region TaskInventoryXmlProcessors 747 #region TaskInventoryXmlProcessors
@@ -1219,6 +1226,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1219 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1226 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1220 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1227 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1221 1228
1229 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1230
1222 writer.WriteEndElement(); 1231 writer.WriteEndElement();
1223 } 1232 }
1224 1233
@@ -1503,12 +1512,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1503 { 1512 {
1504 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1513 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1505 1514
1506 if (reader.IsEmptyElement)
1507 {
1508 reader.Read();
1509 return tinv;
1510 }
1511
1512 reader.ReadStartElement(name, String.Empty); 1515 reader.ReadStartElement(name, String.Empty);
1513 1516
1514 while (reader.Name == "TaskInventoryItem") 1517 while (reader.Name == "TaskInventoryItem")
@@ -1551,12 +1554,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1551 1554
1552 PrimitiveBaseShape shape = new PrimitiveBaseShape(); 1555 PrimitiveBaseShape shape = new PrimitiveBaseShape();
1553 1556
1554 if (reader.IsEmptyElement)
1555 {
1556 reader.Read();
1557 return shape;
1558 }
1559
1560 reader.ReadStartElement(name, String.Empty); // Shape 1557 reader.ReadStartElement(name, String.Empty); // Shape
1561 1558
1562 string nodeName = string.Empty; 1559 string nodeName = string.Empty;
@@ -1596,4 +1593,4 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1596 1593
1597 #endregion 1594 #endregion
1598 } 1595 }
1599} 1596} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index d34d8e5..81f41db 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -30,9 +30,24 @@ using System.Reflection;
30using log4net; 30using log4net;
31using OpenMetaverse; 31using OpenMetaverse;
32using OpenSim.Region.Framework.Interfaces; 32using OpenSim.Region.Framework.Interfaces;
33using System;
33 34
34namespace OpenSim.Region.Framework.Scenes 35namespace OpenSim.Region.Framework.Scenes
35{ 36{
37 [Flags]
38 public enum UndoType
39 {
40 STATE_PRIM_POSITION = 1,
41 STATE_PRIM_ROTATION = 2,
42 STATE_PRIM_SCALE = 4,
43 STATE_PRIM_ALL = 7,
44 STATE_GROUP_POSITION = 8,
45 STATE_GROUP_ROTATION = 16,
46 STATE_GROUP_SCALE = 32,
47 STATE_GROUP_ALL = 56,
48 STATE_ALL = 63
49 }
50
36 public class UndoState 51 public class UndoState
37 { 52 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 53// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -40,6 +55,11 @@ namespace OpenSim.Region.Framework.Scenes
40 public Vector3 Position = Vector3.Zero; 55 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero; 56 public Vector3 Scale = Vector3.Zero;
42 public Quaternion Rotation = Quaternion.Identity; 57 public Quaternion Rotation = Quaternion.Identity;
58 public Vector3 GroupPosition = Vector3.Zero;
59 public Quaternion GroupRotation = Quaternion.Identity;
60 public Vector3 GroupScale = Vector3.Zero;
61 public DateTime LastUpdated = DateTime.Now;
62 public UndoType Type;
43 63
44 /// <summary> 64 /// <summary>
45 /// Is this undo state for an entire group? 65 /// Is this undo state for an entire group?
@@ -58,7 +78,13 @@ namespace OpenSim.Region.Framework.Scenes
58 ForGroup = forGroup; 78 ForGroup = forGroup;
59 79
60// if (ForGroup) 80// if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition; 81 GroupScale = part.ParentGroup.RootPart.Shape.Scale;
82
83 //FUBAR WARNING: Do NOT get the group's absoluteposition here
84 //or you'll experience a loop and/or a stack issue
85 GroupPosition = part.ParentGroup.RootPart.AbsolutePosition;
86 GroupRotation = part.ParentGroup.GroupRotation;
87 Position = part.ParentGroup.RootPart.AbsolutePosition;
62// else 88// else
63// Position = part.OffsetPosition; 89// Position = part.OffsetPosition;
64 90
@@ -90,7 +116,49 @@ namespace OpenSim.Region.Framework.Scenes
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 116// "[UNDO STATE]: Storing undo scale {0} for child part", Scale);
91 } 117 }
92 } 118 }
93 119 public void Merge(UndoState last)
120 {
121 if ((Type & UndoType.STATE_GROUP_POSITION) == 0 || ((last.Type & UndoType.STATE_GROUP_POSITION) >= (Type & UndoType.STATE_GROUP_POSITION)))
122 {
123 GroupPosition = last.GroupPosition;
124 Position = last.Position;
125 }
126 if ((Type & UndoType.STATE_GROUP_SCALE) == 0 || ((last.Type & UndoType.STATE_GROUP_SCALE) >= (Type & UndoType.STATE_GROUP_SCALE)))
127 {
128 GroupScale = last.GroupScale;
129 Scale = last.Scale;
130 }
131 if ((Type & UndoType.STATE_GROUP_ROTATION) == 0 || ((last.Type & UndoType.STATE_GROUP_ROTATION) >= (Type & UndoType.STATE_GROUP_ROTATION)))
132 {
133 GroupRotation = last.GroupRotation;
134 Rotation = last.Rotation;
135 }
136 if ((Type & UndoType.STATE_PRIM_POSITION) == 0 || ((last.Type & UndoType.STATE_PRIM_POSITION) >= (Type & UndoType.STATE_PRIM_POSITION)))
137 {
138 Position = last.Position;
139 }
140 if ((Type & UndoType.STATE_PRIM_SCALE) == 0 || ((last.Type & UndoType.STATE_PRIM_SCALE) >= (Type & UndoType.STATE_PRIM_SCALE)))
141 {
142 Scale = last.Scale;
143 }
144 if ((Type & UndoType.STATE_PRIM_ROTATION) == 0 || ((last.Type & UndoType.STATE_PRIM_ROTATION) >= (Type & UndoType.STATE_PRIM_ROTATION)))
145 {
146 Rotation = last.Rotation;
147 }
148 Type = Type | last.Type;
149 }
150 public bool Compare(UndoState undo)
151 {
152 if (undo == null || Position == null) return false;
153 if (undo.Position == Position && undo.Rotation == Rotation && undo.Scale == Scale && undo.GroupPosition == GroupPosition && undo.GroupScale == GroupScale && undo.GroupRotation == GroupRotation)
154 {
155 return true;
156 }
157 else
158 {
159 return false;
160 }
161 }
94 /// <summary> 162 /// <summary>
95 /// Compare the relevant state in the given part to this state. 163 /// Compare the relevant state in the given part to this state.
96 /// </summary> 164 /// </summary>
@@ -115,7 +183,7 @@ namespace OpenSim.Region.Framework.Scenes
115 return false; 183 return false;
116 } 184 }
117 185
118 public void PlaybackState(SceneObjectPart part) 186 private void RestoreState(SceneObjectPart part)
119 { 187 {
120 part.Undoing = true; 188 part.Undoing = true;
121 189
@@ -249,4 +317,4 @@ namespace OpenSim.Region.Framework.Scenes
249 m_terrainModule.UndoTerrain(m_terrainChannel); 317 m_terrainModule.UndoTerrain(m_terrainChannel);
250 } 318 }
251 } 319 }
252} \ No newline at end of file 320}
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;