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.cs6
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityInventory.cs3
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs11
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEventQueue.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/EventManager.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs422
-rw-r--r--OpenSim/Region/Framework/Scenes/Prioritizer.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPMaterial.cs95
-rw-r--r--OpenSim/Region/Framework/Scenes/SOPVehicle.cs742
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs328
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs676
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs37
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs293
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs1176
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs1105
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs804
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs377
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs122
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs367
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
30 files changed, 5319 insertions, 1361 deletions
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index eb07165..69ce967 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 System.Collections.Generic; 30using System.Collections.Generic;
30using OpenMetaverse; 31using OpenMetaverse;
31using OpenSim.Framework; 32using OpenSim.Framework;
@@ -75,6 +76,10 @@ namespace OpenSim.Region.Framework.Interfaces
75 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns> 76 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
76 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt); 77 ISceneEntity RezSingleAttachmentFromInventory(IScenePresence sp, UUID itemID, uint AttachmentPt);
77 78
79 // Same as above, but also load script states from a separate doc
80 ISceneEntity RezSingleAttachmentFromInventory(
81 IScenePresence presence, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc);
82
78 /// <summary> 83 /// <summary>
79 /// Rez multiple attachments from a user's inventory 84 /// Rez multiple attachments from a user's inventory
80 /// </summary> 85 /// </summary>
@@ -96,7 +101,6 @@ namespace OpenSim.Region.Framework.Interfaces
96 /// <param name="itemID"></param> 101 /// <param name="itemID"></param>
97 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID); 102 void DetachSingleAttachmentToInv(IScenePresence sp, UUID itemID);
98 103
99 /// <summary>
100 /// Update the position of an attachment. 104 /// Update the position of an attachment.
101 /// </summary> 105 /// </summary>
102 /// <param name="sog"></param> 106 /// <param name="sog"></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..76f1641 100644
--- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs
@@ -35,16 +35,18 @@ using OpenSim.Region.Framework.Scenes;
35 35
36namespace OpenSim.Region.Framework.Interfaces 36namespace OpenSim.Region.Framework.Interfaces
37{ 37{
38 public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version);
39
38 public interface IEntityTransferModule 40 public interface IEntityTransferModule
39 { 41 {
40 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, 42 void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position,
41 Vector3 lookAt, uint teleportFlags); 43 Vector3 lookAt, uint teleportFlags);
42 44
45 bool TeleportHome(UUID id, IClientAPI client);
46
43 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, 47 void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination,
44 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq); 48 Vector3 position, Vector3 lookAt, uint teleportFlags, IEventQueue eq);
45 49
46 void TeleportHome(UUID id, IClientAPI client);
47
48 bool Cross(ScenePresence agent, bool isFlying); 50 bool Cross(ScenePresence agent, bool isFlying);
49 51
50 void AgentArrivedAtDestination(UUID agent); 52 void AgentArrivedAtDestination(UUID agent);
@@ -53,7 +55,12 @@ namespace OpenSim.Region.Framework.Interfaces
53 55
54 void EnableChildAgent(ScenePresence agent, GridRegion region); 56 void EnableChildAgent(ScenePresence agent, GridRegion region);
55 57
58 GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos);
59
56 void Cross(SceneObjectGroup sog, Vector3 position, bool silent); 60 void Cross(SceneObjectGroup sog, Vector3 position, bool silent);
61
62 ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version);
63
57 } 64 }
58 65
59 public interface IUserAgentVerificationModule 66 public interface IUserAgentVerificationModule
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/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
index bfa5d17..5512642 100644
--- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs
@@ -59,5 +59,7 @@ namespace OpenSim.Region.Framework.Interfaces
59 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID); 59 void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID);
60 OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono); 60 OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono);
61 OSD BuildEvent(string eventName, OSD eventBody); 61 OSD BuildEvent(string eventName, OSD eventBody);
62 void partPhysicsProperties(uint localID, byte physhapetype, float density, float friction, float bounce, float gravmod, UUID avatarID);
63
62 } 64 }
63} 65}
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 9cab2e1..ce66100 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -69,6 +69,8 @@ namespace OpenSim.Region.Framework.Interfaces
69 69
70 ArrayList GetScriptErrors(UUID itemID); 70 ArrayList GetScriptErrors(UUID itemID);
71 71
72 bool HasScript(UUID itemID, out bool running);
73
72 void SaveAllState(); 74 void SaveAllState();
73 75
74 /// <summary> 76 /// <summary>
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/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 1e1fcb7..853491b 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;
@@ -874,6 +878,26 @@ namespace OpenSim.Region.Framework.Scenes
874 } 878 }
875 } 879 }
876 } 880 }
881 public void TriggerTerrainUpdate()
882 {
883 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
884 if (handlerTerrainUpdate != null)
885 {
886 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
887 {
888 try
889 {
890 d();
891 }
892 catch (Exception e)
893 {
894 m_log.ErrorFormat(
895 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
896 e.Message, e.StackTrace);
897 }
898 }
899 }
900 }
877 901
878 public void TriggerTerrainTick() 902 public void TriggerTerrainTick()
879 { 903 {
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
new file mode 100644
index 0000000..b7b0d27
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -0,0 +1,422 @@
1// Proprietary code of Avination Virtual Limited
2// (c) 2012 Melanie Thielker
3//
4
5using System;
6using System.Timers;
7using System.Collections;
8using System.Collections.Generic;
9using System.IO;
10using System.Diagnostics;
11using System.Reflection;
12using System.Threading;
13using OpenMetaverse;
14using OpenSim.Framework;
15using OpenSim.Region.Framework.Interfaces;
16using OpenSim.Region.Physics.Manager;
17using OpenSim.Region.Framework.Scenes.Serialization;
18using System.Runtime.Serialization.Formatters.Binary;
19using System.Runtime.Serialization;
20using Timer = System.Timers.Timer;
21using log4net;
22
23namespace OpenSim.Region.Framework.Scenes
24{
25 [Serializable]
26 public class KeyframeMotion
27 {
28 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
29
30 public enum PlayMode : int
31 {
32 Forward = 0,
33 Reverse = 1,
34 Loop = 2,
35 PingPong = 3
36 };
37
38 [Flags]
39 public enum DataFormat : int
40 {
41 Translation = 1,
42 Rotation = 2
43 }
44
45 [Serializable]
46 public struct Keyframe
47 {
48 public Vector3? Position;
49 public Quaternion? Rotation;
50 public Quaternion StartRotation;
51 public int TimeMS;
52 public int TimeTotal;
53 public Vector3 AngularVelocity;
54 };
55
56 private Vector3 m_basePosition;
57 private Quaternion m_baseRotation;
58 private Vector3 m_serializedPosition;
59
60 private Keyframe m_currentFrame;
61 private List<Keyframe> m_frames = new List<Keyframe>();
62
63 private Keyframe[] m_keyframes;
64
65 [NonSerialized()]
66 protected Timer m_timer = new Timer();
67
68 [NonSerialized()]
69 private SceneObjectGroup m_group;
70
71 private PlayMode m_mode = PlayMode.Forward;
72 private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation;
73
74 private bool m_running = false;
75 [NonSerialized()]
76 private bool m_selected = false;
77
78 private int m_iterations = 0;
79
80 private const double timerInterval = 50.0;
81
82 public DataFormat Data
83 {
84 get { return m_data; }
85 }
86
87 public bool Selected
88 {
89 set
90 {
91 if (value)
92 {
93 // Once we're let go, recompute positions
94 if (m_selected)
95 UpdateSceneObject(m_group);
96 }
97 else
98 {
99 // Save selection position in case we get moved
100 if (!m_selected)
101 m_serializedPosition = m_group.AbsolutePosition;
102 }
103 m_selected = value; }
104 }
105
106 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
107 {
108 MemoryStream ms = new MemoryStream(data);
109
110 BinaryFormatter fmt = new BinaryFormatter();
111
112 KeyframeMotion newMotion = (KeyframeMotion)fmt.Deserialize(ms);
113
114 // This will be started when position is updated
115 newMotion.m_timer = new Timer();
116 newMotion.m_timer.Interval = (int)timerInterval;
117 newMotion.m_timer.AutoReset = true;
118 newMotion.m_timer.Elapsed += newMotion.OnTimer;
119
120 return newMotion;
121 }
122
123 public void UpdateSceneObject(SceneObjectGroup grp)
124 {
125 m_group = grp;
126 Vector3 offset = grp.AbsolutePosition - m_serializedPosition;
127
128 m_basePosition += offset;
129 m_currentFrame.Position += offset;
130 for (int i = 0 ; i < m_frames.Count ; i++)
131 {
132 Keyframe k = m_frames[i];
133 k.Position += offset;
134 m_frames[i] = k;
135 }
136
137 if (m_running)
138 Start();
139 }
140
141 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
142 {
143 m_mode = mode;
144 m_data = data;
145
146 m_group = grp;
147 m_basePosition = grp.AbsolutePosition;
148 m_baseRotation = grp.GroupRotation;
149
150 m_timer.Interval = (int)timerInterval;
151 m_timer.AutoReset = true;
152 m_timer.Elapsed += OnTimer;
153 }
154
155 public void SetKeyframes(Keyframe[] frames)
156 {
157 m_keyframes = frames;
158 }
159
160 public void Start()
161 {
162 if (m_keyframes.Length > 0)
163 m_timer.Start();
164 m_running = true;
165 }
166
167 public void Stop()
168 {
169 // Failed object creation
170 if (m_timer == null)
171 return;
172 m_timer.Stop();
173
174 m_basePosition = m_group.AbsolutePosition;
175 m_baseRotation = m_group.GroupRotation;
176
177 m_group.RootPart.Velocity = Vector3.Zero;
178 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
179 m_group.SendGroupRootTerseUpdate();
180
181 m_frames.Clear();
182 m_running = false;
183 }
184
185 public void Pause()
186 {
187 m_group.RootPart.Velocity = Vector3.Zero;
188 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
189 m_group.SendGroupRootTerseUpdate();
190
191 m_timer.Stop();
192 m_running = false;
193 }
194
195 private void GetNextList()
196 {
197 m_frames.Clear();
198 Vector3 pos = m_basePosition;
199 Quaternion rot = m_baseRotation;
200
201 if (m_mode == PlayMode.Loop || m_mode == PlayMode.PingPong || m_iterations == 0)
202 {
203 int direction = 1;
204 if (m_mode == PlayMode.Reverse || ((m_mode == PlayMode.PingPong) && ((m_iterations & 1) != 0)))
205 direction = -1;
206
207 int start = 0;
208 int end = m_keyframes.Length;
209// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
210// end = m_keyframes.Length - 1;
211
212 if (direction < 0)
213 {
214 start = m_keyframes.Length - 1;
215 end = -1;
216// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
217// end = 0;
218 }
219
220 for (int i = start; i != end ; i += direction)
221 {
222 Keyframe k = m_keyframes[i];
223
224 if (k.Position.HasValue)
225 k.Position = (k.Position * direction) + pos;
226 else
227 k.Position = pos;
228
229 k.StartRotation = rot;
230 if (k.Rotation.HasValue)
231 {
232 if (direction == -1)
233 k.Rotation = Quaternion.Conjugate((Quaternion)k.Rotation);
234 k.Rotation = rot * k.Rotation;
235 }
236 else
237 {
238 k.Rotation = rot;
239 }
240
241 float angle = 0;
242
243 float aa = k.StartRotation.X * k.StartRotation.X + k.StartRotation.Y * k.StartRotation.Y + k.StartRotation.Z * k.StartRotation.Z + k.StartRotation.W * k.StartRotation.W;
244 float bb = ((Quaternion)k.Rotation).X * ((Quaternion)k.Rotation).X + ((Quaternion)k.Rotation).Y * ((Quaternion)k.Rotation).Y + ((Quaternion)k.Rotation).Z * ((Quaternion)k.Rotation).Z + ((Quaternion)k.Rotation).W * ((Quaternion)k.Rotation).W;
245 float aa_bb = aa * bb;
246
247 if (aa_bb == 0)
248 {
249 angle = 0;
250 }
251 else
252 {
253 float ab = k.StartRotation.X * ((Quaternion)k.Rotation).X +
254 k.StartRotation.Y * ((Quaternion)k.Rotation).Y +
255 k.StartRotation.Z * ((Quaternion)k.Rotation).Z +
256 k.StartRotation.W * ((Quaternion)k.Rotation).W;
257 float q = (ab * ab) / aa_bb;
258
259 if (q > 1.0f)
260 {
261 angle = 0;
262 }
263 else
264 {
265 angle = (float)Math.Acos(2 * q - 1);
266 }
267 }
268
269 k.AngularVelocity = (new Vector3(0, 0, 1) * (Quaternion)k.Rotation) * (angle / (k.TimeMS / 1000));
270 k.TimeTotal = k.TimeMS;
271
272 m_frames.Add(k);
273
274 pos = (Vector3)k.Position;
275 rot = (Quaternion)k.Rotation;
276 }
277
278 m_basePosition = pos;
279 m_baseRotation = rot;
280
281 m_iterations++;
282 }
283 }
284
285 protected void OnTimer(object sender, ElapsedEventArgs e)
286 {
287 if (m_frames.Count == 0)
288 {
289 GetNextList();
290
291 if (m_frames.Count == 0)
292 {
293 Stop();
294 return;
295 }
296
297 m_currentFrame = m_frames[0];
298 }
299
300 if (m_selected)
301 {
302 if (m_group.RootPart.Velocity != Vector3.Zero)
303 {
304 m_group.RootPart.Velocity = Vector3.Zero;
305 m_group.SendGroupRootTerseUpdate();
306 }
307 return;
308 }
309
310 // Do the frame processing
311 double steps = (double)m_currentFrame.TimeMS / timerInterval;
312 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
313
314 if (steps <= 1.0)
315 {
316 m_currentFrame.TimeMS = 0;
317
318 m_group.AbsolutePosition = (Vector3)m_currentFrame.Position;
319 m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
320 }
321 else
322 {
323 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
324 Vector3 motionThisFrame = v / (float)steps;
325 v = v * 1000 / m_currentFrame.TimeMS;
326
327 bool update = false;
328
329 if (Vector3.Mag(motionThisFrame) >= 0.05f)
330 {
331 m_group.AbsolutePosition += motionThisFrame;
332 m_group.RootPart.Velocity = v;
333 update = true;
334 }
335
336 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
337 {
338 Quaternion current = m_group.GroupRotation;
339
340 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
341
342 float angle = 0;
343
344 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
345 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
346 float aa_bb = aa * bb;
347
348 if (aa_bb == 0)
349 {
350 angle = 0;
351 }
352 else
353 {
354 float ab = current.X * step.X +
355 current.Y * step.Y +
356 current.Z * step.Z +
357 current.W * step.W;
358 float q = (ab * ab) / aa_bb;
359
360 if (q > 1.0f)
361 {
362 angle = 0;
363 }
364 else
365 {
366 angle = (float)Math.Acos(2 * q - 1);
367 }
368 }
369
370 if (angle > 0.01f)
371 {
372 m_group.UpdateGroupRotationR(step);
373 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
374 update = true;
375 }
376 }
377
378 if (update)
379 m_group.SendGroupRootTerseUpdate();
380 }
381
382 m_currentFrame.TimeMS -= (int)timerInterval;
383
384 if (m_currentFrame.TimeMS <= 0)
385 {
386 m_group.RootPart.Velocity = Vector3.Zero;
387 m_group.RootPart.UpdateAngularVelocity(Vector3.Zero);
388 m_group.SendGroupRootTerseUpdate();
389
390 m_frames.RemoveAt(0);
391 if (m_frames.Count > 0)
392 m_currentFrame = m_frames[0];
393 }
394 }
395
396 public Byte[] Serialize()
397 {
398 MemoryStream ms = new MemoryStream();
399 m_timer.Stop();
400
401 BinaryFormatter fmt = new BinaryFormatter();
402 SceneObjectGroup tmp = m_group;
403 m_group = null;
404 m_serializedPosition = tmp.AbsolutePosition;
405 fmt.Serialize(ms, this);
406 m_group = tmp;
407 return ms.ToArray();
408 }
409
410 public void CrossingFailure()
411 {
412 // The serialization has stopped the timer, so let's wait a moment
413 // then retry the crossing. We'll get back here if it fails.
414 Util.FireAndForget(delegate (object x)
415 {
416 Thread.Sleep(60000);
417 if (m_running)
418 m_timer.Start();
419 });
420 }
421 }
422}
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/SOPMaterial.cs b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
new file mode 100644
index 0000000..10ac37c
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs
@@ -0,0 +1,95 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32
33namespace OpenSim.Region.Framework.Scenes
34{
35 public static class SOPMaterialData
36 {
37 public enum SopMaterial : int // redundante and not in use for now
38 {
39 Stone = 0,
40 Metal = 1,
41 Glass = 2,
42 Wood = 3,
43 Flesh = 4,
44 Plastic = 5,
45 Rubber = 6,
46 light = 7 // compatibility with old viewers
47 }
48
49 private struct MaterialData
50 {
51 public float friction;
52 public float bounce;
53 public MaterialData(float f, float b)
54 {
55 friction = f;
56 bounce = b;
57 }
58 }
59
60 private static MaterialData[] m_materialdata = {
61 new MaterialData(0.8f,0.4f), // Stone
62 new MaterialData(0.3f,0.4f), // Metal
63 new MaterialData(0.2f,0.7f), // Glass
64 new MaterialData(0.6f,0.5f), // Wood
65 new MaterialData(0.9f,0.3f), // Flesh
66 new MaterialData(0.4f,0.7f), // Plastic
67 new MaterialData(0.9f,0.95f), // Rubber
68 new MaterialData(0.0f,0.0f) // light ??
69 };
70
71 public static Material MaxMaterial
72 {
73 get { return (Material)(m_materialdata.Length - 1); }
74 }
75
76 public static float friction(Material material)
77 {
78 int indx = (int)material;
79 if (indx < m_materialdata.Length)
80 return (m_materialdata[indx].friction);
81 else
82 return 0;
83 }
84
85 public static float bounce(Material material)
86 {
87 int indx = (int)material;
88 if (indx < m_materialdata.Length)
89 return (m_materialdata[indx].bounce);
90 else
91 return 0;
92 }
93
94 }
95} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/SOPVehicle.cs b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
new file mode 100644
index 0000000..d3c2d27
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs
@@ -0,0 +1,742 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
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.
26 */
27
28using System;
29using System.Collections.Generic;
30using OpenMetaverse;
31using OpenSim.Framework;
32using OpenSim.Region.Physics.Manager;
33using System.Xml;
34using OpenSim.Framework.Serialization;
35using OpenSim.Framework.Serialization.External;
36using OpenSim.Region.Framework.Scenes.Serialization;
37using OpenSim.Region.Framework.Scenes.Serialization;
38
39namespace OpenSim.Region.Framework.Scenes
40{
41 public class SOPVehicle
42 {
43 public VehicleData vd;
44
45 public Vehicle Type
46 {
47 get { return vd.m_type; }
48 }
49
50 public SOPVehicle()
51 {
52 vd = new VehicleData();
53 ProcessTypeChange(Vehicle.TYPE_NONE); // is needed?
54 }
55
56 public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
57 {
58 float len;
59 float timestep = 0.01f;
60 switch (pParam)
61 {
62 case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY:
63 if (pValue < 0f) pValue = 0f;
64 if (pValue > 1f) pValue = 1f;
65 vd.m_angularDeflectionEfficiency = pValue;
66 break;
67 case Vehicle.ANGULAR_DEFLECTION_TIMESCALE:
68 if (pValue < timestep) pValue = timestep;
69 vd.m_angularDeflectionTimescale = pValue;
70 break;
71 case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
72 if (pValue < timestep) pValue = timestep;
73 else if (pValue > 120) pValue = 120;
74 vd.m_angularMotorDecayTimescale = pValue;
75 break;
76 case Vehicle.ANGULAR_MOTOR_TIMESCALE:
77 if (pValue < timestep) pValue = timestep;
78 vd.m_angularMotorTimescale = pValue;
79 break;
80 case Vehicle.BANKING_EFFICIENCY:
81 if (pValue < -1f) pValue = -1f;
82 if (pValue > 1f) pValue = 1f;
83 vd.m_bankingEfficiency = pValue;
84 break;
85 case Vehicle.BANKING_MIX:
86 if (pValue < 0f) pValue = 0f;
87 if (pValue > 1f) pValue = 1f;
88 vd.m_bankingMix = pValue;
89 break;
90 case Vehicle.BANKING_TIMESCALE:
91 if (pValue < timestep) pValue = timestep;
92 vd.m_bankingTimescale = pValue;
93 break;
94 case Vehicle.BUOYANCY:
95 if (pValue < -1f) pValue = -1f;
96 if (pValue > 1f) pValue = 1f;
97 vd.m_VehicleBuoyancy = pValue;
98 break;
99 case Vehicle.HOVER_EFFICIENCY:
100 if (pValue < 0f) pValue = 0f;
101 if (pValue > 1f) pValue = 1f;
102 vd.m_VhoverEfficiency = pValue;
103 break;
104 case Vehicle.HOVER_HEIGHT:
105 vd.m_VhoverHeight = pValue;
106 break;
107 case Vehicle.HOVER_TIMESCALE:
108 if (pValue < timestep) pValue = timestep;
109 vd.m_VhoverTimescale = pValue;
110 break;
111 case Vehicle.LINEAR_DEFLECTION_EFFICIENCY:
112 if (pValue < 0f) pValue = 0f;
113 if (pValue > 1f) pValue = 1f;
114 vd.m_linearDeflectionEfficiency = pValue;
115 break;
116 case Vehicle.LINEAR_DEFLECTION_TIMESCALE:
117 if (pValue < timestep) pValue = timestep;
118 vd.m_linearDeflectionTimescale = pValue;
119 break;
120 case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
121 if (pValue < timestep) pValue = timestep;
122 else if (pValue > 120) pValue = 120;
123 vd.m_linearMotorDecayTimescale = pValue;
124 break;
125 case Vehicle.LINEAR_MOTOR_TIMESCALE:
126 if (pValue < timestep) pValue = timestep;
127 vd.m_linearMotorTimescale = pValue;
128 break;
129 case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
130 if (pValue < 0f) pValue = 0f;
131 if (pValue > 1f) pValue = 1f;
132 vd.m_verticalAttractionEfficiency = pValue;
133 break;
134 case Vehicle.VERTICAL_ATTRACTION_TIMESCALE:
135 if (pValue < timestep) pValue = timestep;
136 vd.m_verticalAttractionTimescale = pValue;
137 break;
138
139 // These are vector properties but the engine lets you use a single float value to
140 // set all of the components to the same value
141 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
142 if (pValue < timestep) pValue = timestep;
143 vd.m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
144 break;
145 case Vehicle.ANGULAR_MOTOR_DIRECTION:
146 vd.m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
147 len = vd.m_angularMotorDirection.Length();
148 if (len > 12.566f)
149 vd.m_angularMotorDirection *= (12.566f / len);
150 break;
151 case Vehicle.LINEAR_FRICTION_TIMESCALE:
152 if (pValue < timestep) pValue = timestep;
153 vd.m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
154 break;
155 case Vehicle.LINEAR_MOTOR_DIRECTION:
156 vd.m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
157 len = vd.m_linearMotorDirection.Length();
158 if (len > 30.0f)
159 vd.m_linearMotorDirection *= (30.0f / len);
160 break;
161 case Vehicle.LINEAR_MOTOR_OFFSET:
162 vd.m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
163 len = vd.m_linearMotorOffset.Length();
164 if (len > 100.0f)
165 vd.m_linearMotorOffset *= (100.0f / len);
166 break;
167 }
168 }//end ProcessFloatVehicleParam
169
170 public void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue)
171 {
172 float len;
173 float timestep = 0.01f;
174 switch (pParam)
175 {
176 case Vehicle.ANGULAR_FRICTION_TIMESCALE:
177 if (pValue.X < timestep) pValue.X = timestep;
178 if (pValue.Y < timestep) pValue.Y = timestep;
179 if (pValue.Z < timestep) pValue.Z = timestep;
180
181 vd.m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
182 break;
183 case Vehicle.ANGULAR_MOTOR_DIRECTION:
184 vd.m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
185 // Limit requested angular speed to 2 rps= 4 pi rads/sec
186 len = vd.m_angularMotorDirection.Length();
187 if (len > 12.566f)
188 vd.m_angularMotorDirection *= (12.566f / len);
189 break;
190 case Vehicle.LINEAR_FRICTION_TIMESCALE:
191 if (pValue.X < timestep) pValue.X = timestep;
192 if (pValue.Y < timestep) pValue.Y = timestep;
193 if (pValue.Z < timestep) pValue.Z = timestep;
194 vd.m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
195 break;
196 case Vehicle.LINEAR_MOTOR_DIRECTION:
197 vd.m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
198 len = vd.m_linearMotorDirection.Length();
199 if (len > 30.0f)
200 vd.m_linearMotorDirection *= (30.0f / len);
201 break;
202 case Vehicle.LINEAR_MOTOR_OFFSET:
203 vd.m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
204 len = vd.m_linearMotorOffset.Length();
205 if (len > 100.0f)
206 vd.m_linearMotorOffset *= (100.0f / len);
207 break;
208 }
209 }//end ProcessVectorVehicleParam
210
211 public void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue)
212 {
213 switch (pParam)
214 {
215 case Vehicle.REFERENCE_FRAME:
216 vd.m_referenceFrame = Quaternion.Inverse(pValue);
217 break;
218 }
219 }//end ProcessRotationVehicleParam
220
221 public void ProcessVehicleFlags(int pParam, bool remove)
222 {
223 if (remove)
224 {
225 vd.m_flags &= ~((VehicleFlag)pParam);
226 }
227 else
228 {
229 vd.m_flags |= (VehicleFlag)pParam;
230 }
231 }//end ProcessVehicleFlags
232
233 public void ProcessTypeChange(Vehicle pType)
234 {
235 vd.m_linearMotorDirection = Vector3.Zero;
236 vd.m_angularMotorDirection = Vector3.Zero;
237 vd.m_linearMotorOffset = Vector3.Zero;
238 vd.m_referenceFrame = Quaternion.Identity;
239
240 // Set Defaults For Type
241 vd.m_type = pType;
242 switch (pType)
243 {
244 case Vehicle.TYPE_NONE:
245 vd.m_linearFrictionTimescale = new Vector3(1000, 1000, 1000);
246 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
247 vd.m_linearMotorTimescale = 1000;
248 vd.m_linearMotorDecayTimescale = 120;
249 vd.m_angularMotorTimescale = 1000;
250 vd.m_angularMotorDecayTimescale = 1000;
251 vd.m_VhoverHeight = 0;
252 vd.m_VhoverEfficiency = 1;
253 vd.m_VhoverTimescale = 1000;
254 vd.m_VehicleBuoyancy = 0;
255 vd.m_linearDeflectionEfficiency = 0;
256 vd.m_linearDeflectionTimescale = 1000;
257 vd.m_angularDeflectionEfficiency = 0;
258 vd.m_angularDeflectionTimescale = 1000;
259 vd.m_bankingEfficiency = 0;
260 vd.m_bankingMix = 1;
261 vd.m_bankingTimescale = 1000;
262 vd.m_verticalAttractionEfficiency = 0;
263 vd.m_verticalAttractionTimescale = 1000;
264
265 vd.m_flags = (VehicleFlag)0;
266 break;
267
268 case Vehicle.TYPE_SLED:
269 vd.m_linearFrictionTimescale = new Vector3(30, 1, 1000);
270 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
271 vd.m_linearMotorTimescale = 1000;
272 vd.m_linearMotorDecayTimescale = 120;
273 vd.m_angularMotorTimescale = 1000;
274 vd.m_angularMotorDecayTimescale = 120;
275 vd.m_VhoverHeight = 0;
276 vd.m_VhoverEfficiency = 1;
277 vd.m_VhoverTimescale = 10;
278 vd.m_VehicleBuoyancy = 0;
279 vd.m_linearDeflectionEfficiency = 1;
280 vd.m_linearDeflectionTimescale = 1;
281 vd.m_angularDeflectionEfficiency = 0;
282 vd.m_angularDeflectionTimescale = 1000;
283 vd.m_bankingEfficiency = 0;
284 vd.m_bankingMix = 1;
285 vd.m_bankingTimescale = 10;
286 vd.m_flags &=
287 ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY |
288 VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY);
289 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP);
290 break;
291 case Vehicle.TYPE_CAR:
292 vd.m_linearFrictionTimescale = new Vector3(100, 2, 1000);
293 vd.m_angularFrictionTimescale = new Vector3(1000, 1000, 1000);
294 vd.m_linearMotorTimescale = 1;
295 vd.m_linearMotorDecayTimescale = 60;
296 vd.m_angularMotorTimescale = 1;
297 vd.m_angularMotorDecayTimescale = 0.8f;
298 vd.m_VhoverHeight = 0;
299 vd.m_VhoverEfficiency = 0;
300 vd.m_VhoverTimescale = 1000;
301 vd.m_VehicleBuoyancy = 0;
302 vd.m_linearDeflectionEfficiency = 1;
303 vd.m_linearDeflectionTimescale = 2;
304 vd.m_angularDeflectionEfficiency = 0;
305 vd.m_angularDeflectionTimescale = 10;
306 vd.m_verticalAttractionEfficiency = 1f;
307 vd.m_verticalAttractionTimescale = 10f;
308 vd.m_bankingEfficiency = -0.2f;
309 vd.m_bankingMix = 1;
310 vd.m_bankingTimescale = 1;
311 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT);
312 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY |
313 VehicleFlag.LIMIT_MOTOR_UP | VehicleFlag.HOVER_UP_ONLY);
314 break;
315 case Vehicle.TYPE_BOAT:
316 vd.m_linearFrictionTimescale = new Vector3(10, 3, 2);
317 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
318 vd.m_linearMotorTimescale = 5;
319 vd.m_linearMotorDecayTimescale = 60;
320 vd.m_angularMotorTimescale = 4;
321 vd.m_angularMotorDecayTimescale = 4;
322 vd.m_VhoverHeight = 0;
323 vd.m_VhoverEfficiency = 0.5f;
324 vd.m_VhoverTimescale = 2;
325 vd.m_VehicleBuoyancy = 1;
326 vd.m_linearDeflectionEfficiency = 0.5f;
327 vd.m_linearDeflectionTimescale = 3;
328 vd.m_angularDeflectionEfficiency = 0.5f;
329 vd.m_angularDeflectionTimescale = 5;
330 vd.m_verticalAttractionEfficiency = 0.5f;
331 vd.m_verticalAttractionTimescale = 5f;
332 vd.m_bankingEfficiency = -0.3f;
333 vd.m_bankingMix = 0.8f;
334 vd.m_bankingTimescale = 1;
335 vd.m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY |
336 VehicleFlag.HOVER_GLOBAL_HEIGHT |
337 VehicleFlag.HOVER_UP_ONLY |
338 VehicleFlag.LIMIT_ROLL_ONLY);
339 vd.m_flags |= (VehicleFlag.NO_DEFLECTION_UP |
340 VehicleFlag.LIMIT_MOTOR_UP |
341 VehicleFlag.HOVER_WATER_ONLY);
342 break;
343 case Vehicle.TYPE_AIRPLANE:
344 vd.m_linearFrictionTimescale = new Vector3(200, 10, 5);
345 vd.m_angularFrictionTimescale = new Vector3(20, 20, 20);
346 vd.m_linearMotorTimescale = 2;
347 vd.m_linearMotorDecayTimescale = 60;
348 vd.m_angularMotorTimescale = 4;
349 vd.m_angularMotorDecayTimescale = 8;
350 vd.m_VhoverHeight = 0;
351 vd.m_VhoverEfficiency = 0.5f;
352 vd.m_VhoverTimescale = 1000;
353 vd.m_VehicleBuoyancy = 0;
354 vd.m_linearDeflectionEfficiency = 0.5f;
355 vd.m_linearDeflectionTimescale = 0.5f;
356 vd.m_angularDeflectionEfficiency = 1;
357 vd.m_angularDeflectionTimescale = 2;
358 vd.m_verticalAttractionEfficiency = 0.9f;
359 vd.m_verticalAttractionTimescale = 2f;
360 vd.m_bankingEfficiency = 1;
361 vd.m_bankingMix = 0.7f;
362 vd.m_bankingTimescale = 2;
363 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
364 VehicleFlag.HOVER_TERRAIN_ONLY |
365 VehicleFlag.HOVER_GLOBAL_HEIGHT |
366 VehicleFlag.HOVER_UP_ONLY |
367 VehicleFlag.NO_DEFLECTION_UP |
368 VehicleFlag.LIMIT_MOTOR_UP);
369 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY);
370 break;
371 case Vehicle.TYPE_BALLOON:
372 vd.m_linearFrictionTimescale = new Vector3(5, 5, 5);
373 vd.m_angularFrictionTimescale = new Vector3(10, 10, 10);
374 vd.m_linearMotorTimescale = 5;
375 vd.m_linearMotorDecayTimescale = 60;
376 vd.m_angularMotorTimescale = 6;
377 vd.m_angularMotorDecayTimescale = 10;
378 vd.m_VhoverHeight = 5;
379 vd.m_VhoverEfficiency = 0.8f;
380 vd.m_VhoverTimescale = 10;
381 vd.m_VehicleBuoyancy = 1;
382 vd.m_linearDeflectionEfficiency = 0;
383 vd.m_linearDeflectionTimescale = 5;
384 vd.m_angularDeflectionEfficiency = 0;
385 vd.m_angularDeflectionTimescale = 5;
386 vd.m_verticalAttractionEfficiency = 0f;
387 vd.m_verticalAttractionTimescale = 1000f;
388 vd.m_bankingEfficiency = 0;
389 vd.m_bankingMix = 0.7f;
390 vd.m_bankingTimescale = 5;
391 vd.m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY |
392 VehicleFlag.HOVER_TERRAIN_ONLY |
393 VehicleFlag.HOVER_UP_ONLY |
394 VehicleFlag.NO_DEFLECTION_UP |
395 VehicleFlag.LIMIT_MOTOR_UP);
396 vd.m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY |
397 VehicleFlag.HOVER_GLOBAL_HEIGHT);
398 break;
399 }
400 }
401 public void SetVehicle(PhysicsActor ph)
402 {
403 if (ph == null)
404 return;
405 ph.SetVehicle(vd);
406 }
407
408 private XmlTextWriter writer;
409
410 private void XWint(string name, int i)
411 {
412 writer.WriteElementString(name, i.ToString());
413 }
414
415 private void XWfloat(string name, float f)
416 {
417 writer.WriteElementString(name, f.ToString(Utils.EnUsCulture));
418 }
419
420 private void XWVector(string name, Vector3 vec)
421 {
422 writer.WriteStartElement(name);
423 writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture));
424 writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture));
425 writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture));
426 writer.WriteEndElement();
427 }
428
429 private void XWQuat(string name, Quaternion quat)
430 {
431 writer.WriteStartElement(name);
432 writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture));
433 writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture));
434 writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture));
435 writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture));
436 writer.WriteEndElement();
437 }
438
439 public void ToXml2(XmlTextWriter twriter)
440 {
441 writer = twriter;
442 writer.WriteStartElement("Vehicle");
443
444 XWint("TYPE", (int)vd.m_type);
445 XWint("FLAGS", (int)vd.m_flags);
446
447 // Linear properties
448 XWVector("LMDIR", vd.m_linearMotorDirection);
449 XWVector("LMFTIME", vd.m_linearFrictionTimescale);
450 XWfloat("LMDTIME", vd.m_linearMotorDecayTimescale);
451 XWfloat("LMTIME", vd.m_linearMotorTimescale);
452 XWVector("LMOFF", vd.m_linearMotorOffset);
453
454 //Angular properties
455 XWVector("AMDIR", vd.m_angularMotorDirection);
456 XWfloat("AMTIME", vd.m_angularMotorTimescale);
457 XWfloat("AMDTIME", vd.m_angularMotorDecayTimescale);
458 XWVector("AMFTIME", vd.m_angularFrictionTimescale);
459
460 //Deflection properties
461 XWfloat("ADEFF", vd.m_angularDeflectionEfficiency);
462 XWfloat("ADTIME", vd.m_angularDeflectionTimescale);
463 XWfloat("LDEFF", vd.m_linearDeflectionEfficiency);
464 XWfloat("LDTIME", vd.m_linearDeflectionTimescale);
465
466 //Banking properties
467 XWfloat("BEFF", vd.m_bankingEfficiency);
468 XWfloat("BMIX", vd.m_bankingMix);
469 XWfloat("BTIME", vd.m_bankingTimescale);
470
471 //Hover and Buoyancy properties
472 XWfloat("HHEI", vd.m_VhoverHeight);
473 XWfloat("HEFF", vd.m_VhoverEfficiency);
474 XWfloat("HTIME", vd.m_VhoverTimescale);
475 XWfloat("VBUO", vd.m_VehicleBuoyancy);
476
477 //Attractor properties
478 XWfloat("VAEFF", vd.m_verticalAttractionEfficiency);
479 XWfloat("VATIME", vd.m_verticalAttractionTimescale);
480
481 XWQuat("REF_FRAME", vd.m_referenceFrame);
482
483 writer.WriteEndElement();
484 writer = null;
485 }
486
487
488
489 XmlTextReader reader;
490
491 private int XRint()
492 {
493 return reader.ReadElementContentAsInt();
494 }
495
496 private float XRfloat()
497 {
498 return reader.ReadElementContentAsFloat();
499 }
500
501 public Vector3 XRvector()
502 {
503 Vector3 vec;
504 reader.ReadStartElement();
505 vec.X = reader.ReadElementContentAsFloat();
506 vec.Y = reader.ReadElementContentAsFloat();
507 vec.Z = reader.ReadElementContentAsFloat();
508 reader.ReadEndElement();
509 return vec;
510 }
511
512 public Quaternion XRquat()
513 {
514 Quaternion q;
515 reader.ReadStartElement();
516 q.X = reader.ReadElementContentAsFloat();
517 q.Y = reader.ReadElementContentAsFloat();
518 q.Z = reader.ReadElementContentAsFloat();
519 q.W = reader.ReadElementContentAsFloat();
520 reader.ReadEndElement();
521 return q;
522 }
523
524 public static bool EReadProcessors(
525 Dictionary<string, Action> processors,
526 XmlTextReader xtr)
527 {
528 bool errors = false;
529
530 string nodeName = string.Empty;
531 while (xtr.NodeType != XmlNodeType.EndElement)
532 {
533 nodeName = xtr.Name;
534
535 // m_log.DebugFormat("[ExternalRepresentationUtils]: Processing: {0}", nodeName);
536
537 Action p = null;
538 if (processors.TryGetValue(xtr.Name, out p))
539 {
540 // m_log.DebugFormat("[ExternalRepresentationUtils]: Found {0} processor, nodeName);
541
542 try
543 {
544 p();
545 }
546 catch (Exception e)
547 {
548 errors = true;
549 if (xtr.NodeType == XmlNodeType.EndElement)
550 xtr.Read();
551 }
552 }
553 else
554 {
555 // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName);
556 xtr.ReadOuterXml(); // ignore
557 }
558 }
559
560 return errors;
561 }
562
563
564
565 public void FromXml2(XmlTextReader _reader, out bool errors)
566 {
567 errors = false;
568 reader = _reader;
569
570 Dictionary<string, Action> m_VehicleXmlProcessors
571 = new Dictionary<string, Action>();
572
573 m_VehicleXmlProcessors.Add("TYPE", ProcessXR_type);
574 m_VehicleXmlProcessors.Add("FLAGS", ProcessXR_flags);
575
576 // Linear properties
577 m_VehicleXmlProcessors.Add("LMDIR", ProcessXR_linearMotorDirection);
578 m_VehicleXmlProcessors.Add("LMFTIME", ProcessXR_linearFrictionTimescale);
579 m_VehicleXmlProcessors.Add("LMDTIME", ProcessXR_linearMotorDecayTimescale);
580 m_VehicleXmlProcessors.Add("LMTIME", ProcessXR_linearMotorTimescale);
581 m_VehicleXmlProcessors.Add("LMOFF", ProcessXR_linearMotorOffset);
582
583 //Angular properties
584 m_VehicleXmlProcessors.Add("AMDIR", ProcessXR_angularMotorDirection);
585 m_VehicleXmlProcessors.Add("AMTIME", ProcessXR_angularMotorTimescale);
586 m_VehicleXmlProcessors.Add("AMDTIME", ProcessXR_angularMotorDecayTimescale);
587 m_VehicleXmlProcessors.Add("AMFTIME", ProcessXR_angularFrictionTimescale);
588
589 //Deflection properties
590 m_VehicleXmlProcessors.Add("ADEFF", ProcessXR_angularDeflectionEfficiency);
591 m_VehicleXmlProcessors.Add("ADTIME", ProcessXR_angularDeflectionTimescale);
592 m_VehicleXmlProcessors.Add("LDEFF", ProcessXR_linearDeflectionEfficiency);
593 m_VehicleXmlProcessors.Add("LDTIME", ProcessXR_linearDeflectionTimescale);
594
595 //Banking properties
596 m_VehicleXmlProcessors.Add("BEFF", ProcessXR_bankingEfficiency);
597 m_VehicleXmlProcessors.Add("BMIX", ProcessXR_bankingMix);
598 m_VehicleXmlProcessors.Add("BTIME", ProcessXR_bankingTimescale);
599
600 //Hover and Buoyancy properties
601 m_VehicleXmlProcessors.Add("HHEI", ProcessXR_VhoverHeight);
602 m_VehicleXmlProcessors.Add("HEFF", ProcessXR_VhoverEfficiency);
603 m_VehicleXmlProcessors.Add("HTIME", ProcessXR_VhoverTimescale);
604
605 m_VehicleXmlProcessors.Add("VBUO", ProcessXR_VehicleBuoyancy);
606
607 //Attractor properties
608 m_VehicleXmlProcessors.Add("VAEFF", ProcessXR_verticalAttractionEfficiency);
609 m_VehicleXmlProcessors.Add("VATIME", ProcessXR_verticalAttractionTimescale);
610
611 m_VehicleXmlProcessors.Add("REF_FRAME", ProcessXR_referenceFrame);
612
613 vd = new VehicleData();
614
615 reader.ReadStartElement("Vehicle", String.Empty);
616
617 errors = EReadProcessors(
618 m_VehicleXmlProcessors,
619 reader);
620
621 reader.ReadEndElement();
622 reader = null;
623 }
624
625 private void ProcessXR_type()
626 {
627 vd.m_type = (Vehicle)XRint();
628 }
629 private void ProcessXR_flags()
630 {
631 vd.m_flags = (VehicleFlag)XRint();
632 }
633 // Linear properties
634 private void ProcessXR_linearMotorDirection()
635 {
636 vd.m_linearMotorDirection = XRvector();
637 }
638
639 private void ProcessXR_linearFrictionTimescale()
640 {
641 vd.m_linearFrictionTimescale = XRvector();
642 }
643
644 private void ProcessXR_linearMotorDecayTimescale()
645 {
646 vd.m_linearMotorDecayTimescale = XRfloat();
647 }
648 private void ProcessXR_linearMotorTimescale()
649 {
650 vd.m_linearMotorTimescale = XRfloat();
651 }
652 private void ProcessXR_linearMotorOffset()
653 {
654 vd.m_linearMotorOffset = XRvector();
655 }
656
657
658 //Angular properties
659 private void ProcessXR_angularMotorDirection()
660 {
661 vd.m_angularMotorDirection = XRvector();
662 }
663 private void ProcessXR_angularMotorTimescale()
664 {
665 vd.m_angularMotorTimescale = XRfloat();
666 }
667 private void ProcessXR_angularMotorDecayTimescale()
668 {
669 vd.m_angularMotorDecayTimescale = XRfloat();
670 }
671 private void ProcessXR_angularFrictionTimescale()
672 {
673 vd.m_angularFrictionTimescale = XRvector();
674 }
675
676 //Deflection properties
677 private void ProcessXR_angularDeflectionEfficiency()
678 {
679 vd.m_angularDeflectionEfficiency = XRfloat();
680 }
681 private void ProcessXR_angularDeflectionTimescale()
682 {
683 vd.m_angularDeflectionTimescale = XRfloat();
684 }
685 private void ProcessXR_linearDeflectionEfficiency()
686 {
687 vd.m_linearDeflectionEfficiency = XRfloat();
688 }
689 private void ProcessXR_linearDeflectionTimescale()
690 {
691 vd.m_linearDeflectionTimescale = XRfloat();
692 }
693
694 //Banking properties
695 private void ProcessXR_bankingEfficiency()
696 {
697 vd.m_bankingEfficiency = XRfloat();
698 }
699 private void ProcessXR_bankingMix()
700 {
701 vd.m_bankingMix = XRfloat();
702 }
703 private void ProcessXR_bankingTimescale()
704 {
705 vd.m_bankingTimescale = XRfloat();
706 }
707
708 //Hover and Buoyancy properties
709 private void ProcessXR_VhoverHeight()
710 {
711 vd.m_VhoverHeight = XRfloat();
712 }
713 private void ProcessXR_VhoverEfficiency()
714 {
715 vd.m_VhoverEfficiency = XRfloat();
716 }
717 private void ProcessXR_VhoverTimescale()
718 {
719 vd.m_VhoverTimescale = XRfloat();
720 }
721
722 private void ProcessXR_VehicleBuoyancy()
723 {
724 vd.m_VehicleBuoyancy = XRfloat();
725 }
726
727 //Attractor properties
728 private void ProcessXR_verticalAttractionEfficiency()
729 {
730 vd.m_verticalAttractionEfficiency = XRfloat();
731 }
732 private void ProcessXR_verticalAttractionTimescale()
733 {
734 vd.m_verticalAttractionTimescale = XRfloat();
735 }
736
737 private void ProcessXR_referenceFrame()
738 {
739 vd.m_referenceFrame = XRquat();
740 }
741 }
742} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 6ae4adc..d1739de 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -117,34 +117,22 @@ namespace OpenSim.Region.Framework.Scenes
117 /// <param name="item"></param> 117 /// <param name="item"></param>
118 public bool AddInventoryItem(InventoryItemBase item) 118 public bool AddInventoryItem(InventoryItemBase item)
119 { 119 {
120 if (UUID.Zero == item.Folder) 120 InventoryFolderBase folder;
121
122 if (item.Folder == UUID.Zero)
121 { 123 {
122 InventoryFolderBase f = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType); 124 folder = InventoryService.GetFolderForType(item.Owner, (AssetType)item.AssetType);
123 if (f != null) 125 if (folder == null)
124 { 126 {
125// m_log.DebugFormat( 127 folder = InventoryService.GetRootFolder(item.Owner);
126// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}", 128
127// f.Name, (AssetType)f.Type, item.Name); 129 if (folder == null)
128
129 item.Folder = f.ID;
130 }
131 else
132 {
133 f = InventoryService.GetRootFolder(item.Owner);
134 if (f != null)
135 {
136 item.Folder = f.ID;
137 }
138 else
139 {
140 m_log.WarnFormat(
141 "[AGENT INVENTORY]: Could not find root folder for {0} when trying to add item {1} with no parent folder specified",
142 item.Owner, item.Name);
143 return false; 130 return false;
144 }
145 } 131 }
132
133 item.Folder = folder.ID;
146 } 134 }
147 135
148 if (InventoryService.AddItem(item)) 136 if (InventoryService.AddItem(item))
149 { 137 {
150 int userlevel = 0; 138 int userlevel = 0;
@@ -264,8 +252,7 @@ namespace OpenSim.Region.Framework.Scenes
264 252
265 // Update item with new asset 253 // Update item with new asset
266 item.AssetID = asset.FullID; 254 item.AssetID = asset.FullID;
267 if (group.UpdateInventoryItem(item)) 255 group.UpdateInventoryItem(item);
268 remoteClient.SendAgentAlertMessage("Script saved", false);
269 256
270 part.SendPropertiesToClient(remoteClient); 257 part.SendPropertiesToClient(remoteClient);
271 258
@@ -276,12 +263,7 @@ namespace OpenSim.Region.Framework.Scenes
276 { 263 {
277 // Needs to determine which engine was running it and use that 264 // Needs to determine which engine was running it and use that
278 // 265 //
279 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 266 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
280 errors = part.Inventory.GetScriptErrors(item.ItemID);
281 }
282 else
283 {
284 remoteClient.SendAgentAlertMessage("Script saved", false);
285 } 267 }
286 268
287 // Tell anyone managing scripts that a script has been reloaded/changed 269 // Tell anyone managing scripts that a script has been reloaded/changed
@@ -349,6 +331,7 @@ namespace OpenSim.Region.Framework.Scenes
349 331
350 if (UUID.Zero == transactionID) 332 if (UUID.Zero == transactionID)
351 { 333 {
334 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
352 item.Name = itemUpd.Name; 335 item.Name = itemUpd.Name;
353 item.Description = itemUpd.Description; 336 item.Description = itemUpd.Description;
354 337
@@ -736,6 +719,8 @@ namespace OpenSim.Region.Framework.Scenes
736 return; 719 return;
737 } 720 }
738 721
722 if (newName == null) newName = item.Name;
723
739 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 724 AssetBase asset = AssetService.Get(item.AssetID.ToString());
740 725
741 if (asset != null) 726 if (asset != null)
@@ -792,6 +777,24 @@ namespace OpenSim.Region.Framework.Scenes
792 } 777 }
793 778
794 /// <summary> 779 /// <summary>
780 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
781 /// </summary>
782 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
783 {
784 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
785 foreach (InventoryItemBase b in items)
786 {
787 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
788 InventoryItemBase n = InventoryService.GetItem(b);
789 n.Folder = destfolder;
790 moveitems.Add(n);
791 remoteClient.SendInventoryItemCreateUpdate(n, 0);
792 }
793
794 MoveInventoryItem(remoteClient, moveitems);
795 }
796
797 /// <summary>
795 /// Move an item within the agent's inventory. 798 /// Move an item within the agent's inventory.
796 /// </summary> 799 /// </summary>
797 /// <param name="remoteClient"></param> 800 /// <param name="remoteClient"></param>
@@ -1134,6 +1137,10 @@ namespace OpenSim.Region.Framework.Scenes
1134 { 1137 {
1135 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1138 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1136 1139
1140 // Can't move a null item
1141 if (itemId == UUID.Zero)
1142 return;
1143
1137 if (null == part) 1144 if (null == part)
1138 { 1145 {
1139 m_log.WarnFormat( 1146 m_log.WarnFormat(
@@ -1243,6 +1250,10 @@ namespace OpenSim.Region.Framework.Scenes
1243 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) 1250 if ((part.OwnerID != destPart.OwnerID) && ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0))
1244 return; 1251 return;
1245 1252
1253 bool overrideNoMod = false;
1254 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1255 overrideNoMod = true;
1256
1246 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) 1257 if (part.OwnerID != destPart.OwnerID && (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1247 { 1258 {
1248 // object cannot copy items to an object owned by a different owner 1259 // object cannot copy items to an object owned by a different owner
@@ -1252,7 +1263,7 @@ namespace OpenSim.Region.Framework.Scenes
1252 } 1263 }
1253 1264
1254 // must have both move and modify permission to put an item in an object 1265 // must have both move and modify permission to put an item in an object
1255 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1266 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1256 { 1267 {
1257 return; 1268 return;
1258 } 1269 }
@@ -1311,6 +1322,14 @@ namespace OpenSim.Region.Framework.Scenes
1311 1322
1312 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1323 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1313 { 1324 {
1325 SceneObjectPart destPart = GetSceneObjectPart(destID);
1326 if (destPart != null) // Move into a prim
1327 {
1328 foreach(UUID itemID in items)
1329 MoveTaskInventoryItem(destID, host, itemID);
1330 return destID; // Prim folder ID == prim ID
1331 }
1332
1314 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1333 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1315 1334
1316 UUID newFolderID = UUID.Random(); 1335 UUID newFolderID = UUID.Random();
@@ -1496,12 +1515,12 @@ namespace OpenSim.Region.Framework.Scenes
1496 agentTransactions.HandleTaskItemUpdateFromTransaction( 1515 agentTransactions.HandleTaskItemUpdateFromTransaction(
1497 remoteClient, part, transactionID, currentItem); 1516 remoteClient, part, transactionID, currentItem);
1498 1517
1499 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1518// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1500 remoteClient.SendAgentAlertMessage("Notecard saved", false); 1519// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1501 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1520// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1502 remoteClient.SendAgentAlertMessage("Script saved", false); 1521// remoteClient.SendAgentAlertMessage("Script saved", false);
1503 else 1522// else
1504 remoteClient.SendAgentAlertMessage("Item saved", false); 1523// remoteClient.SendAgentAlertMessage("Item saved", false);
1505 } 1524 }
1506 } 1525 }
1507 1526
@@ -1685,7 +1704,7 @@ namespace OpenSim.Region.Framework.Scenes
1685 } 1704 }
1686 1705
1687 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1706 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1688 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1707 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1689 agentID); 1708 agentID);
1690 AssetService.Store(asset); 1709 AssetService.Store(asset);
1691 1710
@@ -1841,23 +1860,32 @@ namespace OpenSim.Region.Framework.Scenes
1841 // build a list of eligible objects 1860 // build a list of eligible objects
1842 List<uint> deleteIDs = new List<uint>(); 1861 List<uint> deleteIDs = new List<uint>();
1843 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1862 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1844 1863 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1845 // Start with true for both, then remove the flags if objects
1846 // that we can't derez are part of the selection
1847 bool permissionToTake = true;
1848 bool permissionToTakeCopy = true;
1849 bool permissionToDelete = true;
1850 1864
1851 foreach (uint localID in localIDs) 1865 foreach (uint localID in localIDs)
1852 { 1866 {
1867 // Start with true for both, then remove the flags if objects
1868 // that we can't derez are part of the selection
1869 bool permissionToTake = true;
1870 bool permissionToTakeCopy = true;
1871 bool permissionToDelete = true;
1872
1853 // Invalid id 1873 // Invalid id
1854 SceneObjectPart part = GetSceneObjectPart(localID); 1874 SceneObjectPart part = GetSceneObjectPart(localID);
1855 if (part == null) 1875 if (part == null)
1876 {
1877 //Client still thinks the object exists, kill it
1878 deleteIDs.Add(localID);
1856 continue; 1879 continue;
1880 }
1857 1881
1858 // Already deleted by someone else 1882 // Already deleted by someone else
1859 if (part.ParentGroup.IsDeleted) 1883 if (part.ParentGroup.IsDeleted)
1884 {
1885 //Client still thinks the object exists, kill it
1886 deleteIDs.Add(localID);
1860 continue; 1887 continue;
1888 }
1861 1889
1862 // Can't delete child prims 1890 // Can't delete child prims
1863 if (part != part.ParentGroup.RootPart) 1891 if (part != part.ParentGroup.RootPart)
@@ -1865,9 +1893,6 @@ namespace OpenSim.Region.Framework.Scenes
1865 1893
1866 SceneObjectGroup grp = part.ParentGroup; 1894 SceneObjectGroup grp = part.ParentGroup;
1867 1895
1868 deleteIDs.Add(localID);
1869 deleteGroups.Add(grp);
1870
1871 if (remoteClient == null) 1896 if (remoteClient == null)
1872 { 1897 {
1873 // Autoreturn has a null client. Nothing else does. So 1898 // Autoreturn has a null client. Nothing else does. So
@@ -1884,83 +1909,195 @@ namespace OpenSim.Region.Framework.Scenes
1884 } 1909 }
1885 else 1910 else
1886 { 1911 {
1887 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1912 if (action == DeRezAction.TakeCopy)
1913 {
1914 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1915 permissionToTakeCopy = false;
1916 }
1917 else
1918 {
1888 permissionToTakeCopy = false; 1919 permissionToTakeCopy = false;
1889 1920 }
1890 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1921 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1891 permissionToTake = false; 1922 permissionToTake = false;
1892 1923
1893 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1924 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1894 permissionToDelete = false; 1925 permissionToDelete = false;
1895 } 1926 }
1896 }
1897 1927
1898 // Handle god perms 1928 // Handle god perms
1899 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1929 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1900 { 1930 {
1901 permissionToTake = true; 1931 permissionToTake = true;
1902 permissionToTakeCopy = true; 1932 permissionToTakeCopy = true;
1903 permissionToDelete = true; 1933 permissionToDelete = true;
1904 } 1934 }
1905 1935
1906 // If we're re-saving, we don't even want to delete 1936 // If we're re-saving, we don't even want to delete
1907 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1937 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1908 permissionToDelete = false; 1938 permissionToDelete = false;
1909 1939
1910 // if we want to take a copy, we also don't want to delete 1940 // if we want to take a copy, we also don't want to delete
1911 // Note: after this point, the permissionToTakeCopy flag 1941 // Note: after this point, the permissionToTakeCopy flag
1912 // becomes irrelevant. It already includes the permissionToTake 1942 // becomes irrelevant. It already includes the permissionToTake
1913 // permission and after excluding no copy items here, we can 1943 // permission and after excluding no copy items here, we can
1914 // just use that. 1944 // just use that.
1915 if (action == DeRezAction.TakeCopy) 1945 if (action == DeRezAction.TakeCopy)
1916 { 1946 {
1917 // If we don't have permission, stop right here 1947 // If we don't have permission, stop right here
1918 if (!permissionToTakeCopy) 1948 if (!permissionToTakeCopy)
1919 return; 1949 return;
1920 1950
1921 permissionToTake = true; 1951 permissionToTake = true;
1922 // Don't delete 1952 // Don't delete
1923 permissionToDelete = false; 1953 permissionToDelete = false;
1924 } 1954 }
1925 1955
1926 if (action == DeRezAction.Return) 1956 if (action == DeRezAction.Return)
1927 {
1928 if (remoteClient != null)
1929 { 1957 {
1930 if (Permissions.CanReturnObjects( 1958 if (remoteClient != null)
1931 null,
1932 remoteClient.AgentId,
1933 deleteGroups))
1934 { 1959 {
1935 permissionToTake = true; 1960 if (Permissions.CanReturnObjects(
1936 permissionToDelete = true; 1961 null,
1937 1962 remoteClient.AgentId,
1938 foreach (SceneObjectGroup g in deleteGroups) 1963 deleteGroups))
1939 { 1964 {
1940 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 1965 permissionToTake = true;
1966 permissionToDelete = true;
1967
1968 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1941 } 1969 }
1942 } 1970 }
1971 else // Auto return passes through here with null agent
1972 {
1973 permissionToTake = true;
1974 permissionToDelete = true;
1975 }
1943 } 1976 }
1944 else // Auto return passes through here with null agent 1977
1978 if (permissionToTake && (!permissionToDelete))
1979 takeGroups.Add(grp);
1980
1981 if (permissionToDelete)
1945 { 1982 {
1946 permissionToTake = true; 1983 if (permissionToTake)
1947 permissionToDelete = true; 1984 deleteGroups.Add(grp);
1985 deleteIDs.Add(grp.LocalId);
1948 } 1986 }
1949 } 1987 }
1950 1988
1951 if (permissionToTake) 1989 SendKillObject(deleteIDs);
1990
1991 if (deleteGroups.Count > 0)
1952 { 1992 {
1993 foreach (SceneObjectGroup g in deleteGroups)
1994 deleteIDs.Remove(g.LocalId);
1995
1953 m_asyncSceneObjectDeleter.DeleteToInventory( 1996 m_asyncSceneObjectDeleter.DeleteToInventory(
1954 action, destinationID, deleteGroups, remoteClient, 1997 action, destinationID, deleteGroups, remoteClient,
1955 permissionToDelete); 1998 true);
1999 }
2000 if (takeGroups.Count > 0)
2001 {
2002 m_asyncSceneObjectDeleter.DeleteToInventory(
2003 action, destinationID, takeGroups, remoteClient,
2004 false);
1956 } 2005 }
1957 else if (permissionToDelete) 2006 if (deleteIDs.Count > 0)
1958 { 2007 {
1959 foreach (SceneObjectGroup g in deleteGroups) 2008 foreach (SceneObjectGroup g in deleteGroups)
1960 DeleteSceneObject(g, false); 2009 DeleteSceneObject(g, true);
1961 } 2010 }
1962 } 2011 }
1963 2012
2013 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2014 {
2015 itemID = UUID.Zero;
2016 if (grp != null)
2017 {
2018 Vector3 inventoryStoredPosition = new Vector3
2019 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
2020 ? 250
2021 : grp.AbsolutePosition.X)
2022 ,
2023 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
2024 ? 250
2025 : grp.AbsolutePosition.X,
2026 grp.AbsolutePosition.Z);
2027
2028 Vector3 originalPosition = grp.AbsolutePosition;
2029
2030 grp.AbsolutePosition = inventoryStoredPosition;
2031
2032 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2033
2034 grp.AbsolutePosition = originalPosition;
2035
2036 AssetBase asset = CreateAsset(
2037 grp.GetPartName(grp.LocalId),
2038 grp.GetPartDescription(grp.LocalId),
2039 (sbyte)AssetType.Object,
2040 Utils.StringToBytes(sceneObjectXml),
2041 remoteClient.AgentId);
2042 AssetService.Store(asset);
2043
2044 InventoryItemBase item = new InventoryItemBase();
2045 item.CreatorId = grp.RootPart.CreatorID.ToString();
2046 item.CreatorData = grp.RootPart.CreatorData;
2047 item.Owner = remoteClient.AgentId;
2048 item.ID = UUID.Random();
2049 item.AssetID = asset.FullID;
2050 item.Description = asset.Description;
2051 item.Name = asset.Name;
2052 item.AssetType = asset.Type;
2053 item.InvType = (int)InventoryType.Object;
2054
2055 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
2056 if (folder != null)
2057 item.Folder = folder.ID;
2058 else // oopsies
2059 item.Folder = UUID.Zero;
2060
2061 // Set up base perms properly
2062 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2063 permsBase &= grp.RootPart.BaseMask;
2064 permsBase |= (uint)PermissionMask.Move;
2065
2066 // Make sure we don't lock it
2067 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2068
2069 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2070 {
2071 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2072 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2073 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2074 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2075 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2076 }
2077 else
2078 {
2079 item.BasePermissions = permsBase;
2080 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2081 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2082 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2083 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2084 }
2085 item.CreationDate = Util.UnixTimeSinceEpoch();
2086
2087 // sets itemID so client can show item as 'attached' in inventory
2088 grp.SetFromItemID(item.ID);
2089
2090 if (AddInventoryItem(item))
2091 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2092 else
2093 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2094
2095 itemID = item.ID;
2096 return item.AssetID;
2097 }
2098 return UUID.Zero;
2099 }
2100
1964 /// <summary> 2101 /// <summary>
1965 /// Event Handler Rez an object into a scene 2102 /// Event Handler Rez an object into a scene
1966 /// Calls the non-void event handler 2103 /// Calls the non-void event handler
@@ -2087,6 +2224,9 @@ namespace OpenSim.Region.Framework.Scenes
2087 2224
2088 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2225 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2089 { 2226 {
2227 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2228 return;
2229
2090 SceneObjectPart part = GetSceneObjectPart(objectID); 2230 SceneObjectPart part = GetSceneObjectPart(objectID);
2091 if (part == null) 2231 if (part == null)
2092 return; 2232 return;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 87ffc74..35ac908 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -138,12 +138,12 @@ namespace OpenSim.Region.Framework.Scenes
138 { 138 {
139 SceneObjectGroup sog = part.ParentGroup; 139 SceneObjectGroup sog = part.ParentGroup;
140 sog.SendPropertiesToClient(remoteClient); 140 sog.SendPropertiesToClient(remoteClient);
141 sog.IsSelected = true;
142 141
143 // A prim is only tainted if it's allowed to be edited by the person clicking it. 142 // A prim is only tainted if it's allowed to be edited by the person clicking it.
144 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) 143 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
145 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) 144 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
146 { 145 {
146 sog.IsSelected = true;
147 EventManager.TriggerParcelPrimCountTainted(); 147 EventManager.TriggerParcelPrimCountTainted();
148 } 148 }
149 } 149 }
@@ -215,7 +215,9 @@ namespace OpenSim.Region.Framework.Scenes
215 // handled by group, but by prim. Legacy cruft. 215 // handled by group, but by prim. Legacy cruft.
216 // TODO: Make selection flagging per prim! 216 // TODO: Make selection flagging per prim!
217 // 217 //
218 part.ParentGroup.IsSelected = false; 218 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
219 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
220 part.ParentGroup.IsSelected = false;
219 221
220 if (part.ParentGroup.IsAttachment) 222 if (part.ParentGroup.IsAttachment)
221 isAttachment = true; 223 isAttachment = true;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 76e632e..44a738e 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -113,6 +113,7 @@ namespace OpenSim.Region.Framework.Scenes
113 // TODO: need to figure out how allow client agents but deny 113 // TODO: need to figure out how allow client agents but deny
114 // root agents when ACL denies access to root agent 114 // root agents when ACL denies access to root agent
115 public bool m_strictAccessControl = true; 115 public bool m_strictAccessControl = true;
116 public bool m_seeIntoBannedRegion = false;
116 public int MaxUndoCount = 5; 117 public int MaxUndoCount = 5;
117 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 118 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
118 public bool LoginLock = false; 119 public bool LoginLock = false;
@@ -128,12 +129,14 @@ namespace OpenSim.Region.Framework.Scenes
128 129
129 protected int m_splitRegionID; 130 protected int m_splitRegionID;
130 protected Timer m_restartWaitTimer = new Timer(); 131 protected Timer m_restartWaitTimer = new Timer();
132 protected Timer m_timerWatchdog = new Timer();
131 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 133 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
132 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 134 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
133 protected string m_simulatorVersion = "OpenSimulator Server"; 135 protected string m_simulatorVersion = "OpenSimulator Server";
134 protected ModuleLoader m_moduleLoader; 136 protected ModuleLoader m_moduleLoader;
135 protected AgentCircuitManager m_authenticateHandler; 137 protected AgentCircuitManager m_authenticateHandler;
136 protected SceneCommunicationService m_sceneGridService; 138 protected SceneCommunicationService m_sceneGridService;
139 protected ISnmpModule m_snmpService = null;
137 140
138 protected ISimulationDataService m_SimulationDataService; 141 protected ISimulationDataService m_SimulationDataService;
139 protected IEstateDataService m_EstateDataService; 142 protected IEstateDataService m_EstateDataService;
@@ -186,7 +189,7 @@ namespace OpenSim.Region.Framework.Scenes
186 private int m_update_events = 1; 189 private int m_update_events = 1;
187 private int m_update_backup = 200; 190 private int m_update_backup = 200;
188 private int m_update_terrain = 50; 191 private int m_update_terrain = 50;
189// private int m_update_land = 1; 192 private int m_update_land = 10;
190 private int m_update_coarse_locations = 50; 193 private int m_update_coarse_locations = 50;
191 194
192 private int agentMS; 195 private int agentMS;
@@ -205,6 +208,7 @@ namespace OpenSim.Region.Framework.Scenes
205 /// </summary> 208 /// </summary>
206 private int m_lastFrameTick; 209 private int m_lastFrameTick;
207 210
211 public bool CombineRegions = false;
208 /// <summary> 212 /// <summary>
209 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched 213 /// Signals whether temporary objects are currently being cleaned up. Needed because this is launched
210 /// asynchronously from the update loop. 214 /// asynchronously from the update loop.
@@ -227,12 +231,15 @@ namespace OpenSim.Region.Framework.Scenes
227 private bool m_scripts_enabled = true; 231 private bool m_scripts_enabled = true;
228 private string m_defaultScriptEngine; 232 private string m_defaultScriptEngine;
229 private int m_LastLogin; 233 private int m_LastLogin;
230 private Thread HeartbeatThread; 234 private Thread HeartbeatThread = null;
231 private volatile bool shuttingdown; 235 private volatile bool shuttingdown;
232 236
233 private int m_lastUpdate; 237 private int m_lastUpdate;
238 private int m_lastIncoming;
239 private int m_lastOutgoing;
234 private bool m_firstHeartbeat = true; 240 private bool m_firstHeartbeat = true;
235 241 private int m_hbRestarts = 0;
242
236 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; 243 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
237 private bool m_reprioritizationEnabled = true; 244 private bool m_reprioritizationEnabled = true;
238 private double m_reprioritizationInterval = 5000.0; 245 private double m_reprioritizationInterval = 5000.0;
@@ -276,6 +283,19 @@ namespace OpenSim.Region.Framework.Scenes
276 get { return m_sceneGridService; } 283 get { return m_sceneGridService; }
277 } 284 }
278 285
286 public ISnmpModule SnmpService
287 {
288 get
289 {
290 if (m_snmpService == null)
291 {
292 m_snmpService = RequestModuleInterface<ISnmpModule>();
293 }
294
295 return m_snmpService;
296 }
297 }
298
279 public ISimulationDataService SimulationDataService 299 public ISimulationDataService SimulationDataService
280 { 300 {
281 get 301 get
@@ -557,6 +577,9 @@ namespace OpenSim.Region.Framework.Scenes
557 m_EstateDataService = estateDataService; 577 m_EstateDataService = estateDataService;
558 m_regionHandle = m_regInfo.RegionHandle; 578 m_regionHandle = m_regInfo.RegionHandle;
559 m_regionName = m_regInfo.RegionName; 579 m_regionName = m_regInfo.RegionName;
580 m_lastUpdate = Util.EnvironmentTickCount();
581 m_lastIncoming = 0;
582 m_lastOutgoing = 0;
560 583
561 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 584 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
562 m_asyncSceneObjectDeleter.Enabled = true; 585 m_asyncSceneObjectDeleter.Enabled = true;
@@ -641,96 +664,106 @@ namespace OpenSim.Region.Framework.Scenes
641 664
642 // Region config overrides global config 665 // Region config overrides global config
643 // 666 //
644 if (m_config.Configs["Startup"] != null) 667 try
645 { 668 {
646 IConfig startupConfig = m_config.Configs["Startup"]; 669 if (m_config.Configs["Startup"] != null)
670 {
671 IConfig startupConfig = m_config.Configs["Startup"];
647 672
648 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance); 673 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
649 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup); 674 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
650 if (!m_useBackup) 675 if (!m_useBackup)
651 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName); 676 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
652 677
653 //Animation states 678 //Animation states
654 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false); 679 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
655 680
656 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); 681 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
657 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); 682 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
658 683
659 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); 684 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
660 if (RegionInfo.NonphysPrimMax > 0) 685 if (RegionInfo.NonphysPrimMax > 0)
661 { 686 {
662 m_maxNonphys = RegionInfo.NonphysPrimMax; 687 m_maxNonphys = RegionInfo.NonphysPrimMax;
663 } 688 }
664 689
665 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 690 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
666 691
667 if (RegionInfo.PhysPrimMax > 0) 692 if (RegionInfo.PhysPrimMax > 0)
668 { 693 {
669 m_maxPhys = RegionInfo.PhysPrimMax; 694 m_maxPhys = RegionInfo.PhysPrimMax;
670 } 695 }
671 696
672 // Here, if clamping is requested in either global or 697 // Here, if clamping is requested in either global or
673 // local config, it will be used 698 // local config, it will be used
674 // 699 //
675 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize); 700 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
676 if (RegionInfo.ClampPrimSize) 701 if (RegionInfo.ClampPrimSize)
677 { 702 {
678 m_clampPrimSize = true; 703 m_clampPrimSize = true;
679 } 704 }
680 705
681 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 706 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
682 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 707 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
683 m_dontPersistBefore = 708 m_dontPersistBefore =
684 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); 709 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
685 m_dontPersistBefore *= 10000000; 710 m_dontPersistBefore *= 10000000;
686 m_persistAfter = 711 m_persistAfter =
687 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE); 712 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
688 m_persistAfter *= 10000000; 713 m_persistAfter *= 10000000;
689 714
690 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 715 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
716 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
691 717
692 IConfig packetConfig = m_config.Configs["PacketPool"]; 718 IConfig packetConfig = m_config.Configs["PacketPool"];
693 if (packetConfig != null) 719 if (packetConfig != null)
694 { 720 {
695 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); 721 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
696 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); 722 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
697 } 723 }
698 724
699 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 725 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
726 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
727 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
700 728
701 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 729 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
702 if (m_generateMaptiles) 730 if (m_generateMaptiles)
703 {
704 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
705 if (maptileRefresh != 0)
706 { 731 {
707 m_mapGenerationTimer.Interval = maptileRefresh * 1000; 732 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
708 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister; 733 if (maptileRefresh != 0)
709 m_mapGenerationTimer.AutoReset = true; 734 {
710 m_mapGenerationTimer.Start(); 735 m_mapGenerationTimer.Interval = maptileRefresh * 1000;
736 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister;
737 m_mapGenerationTimer.AutoReset = true;
738 m_mapGenerationTimer.Start();
739 }
711 } 740 }
712 } 741 else
713 else
714 {
715 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
716 UUID tileID;
717
718 if (UUID.TryParse(tile, out tileID))
719 { 742 {
720 RegionInfo.RegionSettings.TerrainImageID = tileID; 743 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
744 UUID tileID;
745
746 if (UUID.TryParse(tile, out tileID))
747 {
748 RegionInfo.RegionSettings.TerrainImageID = tileID;
749 }
721 } 750 }
722 }
723 751
724 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime); 752 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
725 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup); 753 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup);
726 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 754 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
727 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement); 755 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement);
728 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events); 756 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events);
729 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects); 757 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
730 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics); 758 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
731 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences); 759 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
732 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain); 760 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
733 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning); 761 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
762 }
763 }
764 catch (Exception e)
765 {
766 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
734 } 767 }
735 768
736 #endregion Region Config 769 #endregion Region Config
@@ -1161,7 +1194,22 @@ namespace OpenSim.Region.Framework.Scenes
1161 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1194 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1162 if (HeartbeatThread != null) 1195 if (HeartbeatThread != null)
1163 { 1196 {
1197 m_hbRestarts++;
1198 if(m_hbRestarts > 10)
1199 Environment.Exit(1);
1200 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1201
1202//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1203//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1204//proc.EnableRaisingEvents=false;
1205//proc.StartInfo.FileName = "/bin/kill";
1206//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1207//proc.Start();
1208//proc.WaitForExit();
1209//Thread.Sleep(1000);
1210//Environment.Exit(1);
1164 HeartbeatThread.Abort(); 1211 HeartbeatThread.Abort();
1212 Watchdog.AbortThread(HeartbeatThread.ManagedThreadId);
1165 HeartbeatThread = null; 1213 HeartbeatThread = null;
1166 } 1214 }
1167 m_lastUpdate = Util.EnvironmentTickCount(); 1215 m_lastUpdate = Util.EnvironmentTickCount();
@@ -1215,9 +1263,6 @@ namespace OpenSim.Region.Framework.Scenes
1215 1263
1216 while (!shuttingdown) 1264 while (!shuttingdown)
1217 Update(-1); 1265 Update(-1);
1218
1219 m_lastUpdate = Util.EnvironmentTickCount();
1220 m_firstHeartbeat = false;
1221 } 1266 }
1222 finally 1267 finally
1223 { 1268 {
@@ -1418,9 +1463,15 @@ namespace OpenSim.Region.Framework.Scenes
1418 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); 1463 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc);
1419 maintc = (int)(MinFrameTime * 1000) - maintc; 1464 maintc = (int)(MinFrameTime * 1000) - maintc;
1420 1465
1466 m_lastUpdate = Util.EnvironmentTickCount();
1467 m_firstHeartbeat = false;
1468
1421 if (maintc > 0) 1469 if (maintc > 0)
1422 Thread.Sleep(maintc); 1470 Thread.Sleep(maintc);
1423 1471
1472 m_lastUpdate = Util.EnvironmentTickCount();
1473 m_firstHeartbeat = false;
1474
1424 // Optionally warn if a frame takes double the amount of time that it should. 1475 // Optionally warn if a frame takes double the amount of time that it should.
1425 if (DebugUpdates 1476 if (DebugUpdates
1426 && Util.EnvironmentTickCountSubtract( 1477 && Util.EnvironmentTickCountSubtract(
@@ -1447,9 +1498,9 @@ namespace OpenSim.Region.Framework.Scenes
1447 1498
1448 private void CheckAtTargets() 1499 private void CheckAtTargets()
1449 { 1500 {
1450 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1501 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1451 lock (m_groupsWithTargets) 1502 lock (m_groupsWithTargets)
1452 objs = m_groupsWithTargets.Values; 1503 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1453 1504
1454 foreach (SceneObjectGroup entry in objs) 1505 foreach (SceneObjectGroup entry in objs)
1455 entry.checkAtTargets(); 1506 entry.checkAtTargets();
@@ -1530,7 +1581,7 @@ namespace OpenSim.Region.Framework.Scenes
1530 msg.fromAgentName = "Server"; 1581 msg.fromAgentName = "Server";
1531 msg.dialog = (byte)19; // Object msg 1582 msg.dialog = (byte)19; // Object msg
1532 msg.fromGroup = false; 1583 msg.fromGroup = false;
1533 msg.offline = (byte)0; 1584 msg.offline = (byte)1;
1534 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1585 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1535 msg.Position = Vector3.Zero; 1586 msg.Position = Vector3.Zero;
1536 msg.RegionID = RegionInfo.RegionID.Guid; 1587 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1768,14 +1819,24 @@ namespace OpenSim.Region.Framework.Scenes
1768 /// <returns></returns> 1819 /// <returns></returns>
1769 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1820 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1770 { 1821 {
1822
1823 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1824 Vector3 wpos = Vector3.Zero;
1825 // Check for water surface intersection from above
1826 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1827 {
1828 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1829 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1830 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1831 wpos.Z = wheight;
1832 }
1833
1771 Vector3 pos = Vector3.Zero; 1834 Vector3 pos = Vector3.Zero;
1772 if (RayEndIsIntersection == (byte)1) 1835 if (RayEndIsIntersection == (byte)1)
1773 { 1836 {
1774 pos = RayEnd; 1837 pos = RayEnd;
1775 return pos;
1776 } 1838 }
1777 1839 else if (RayTargetID != UUID.Zero)
1778 if (RayTargetID != UUID.Zero)
1779 { 1840 {
1780 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1841 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1781 1842
@@ -1797,7 +1858,7 @@ namespace OpenSim.Region.Framework.Scenes
1797 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1858 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1798 1859
1799 // Un-comment out the following line to Get Raytrace results printed to the console. 1860 // Un-comment out the following line to Get Raytrace results printed to the console.
1800 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1861 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1801 float ScaleOffset = 0.5f; 1862 float ScaleOffset = 0.5f;
1802 1863
1803 // If we hit something 1864 // If we hit something
@@ -1820,13 +1881,10 @@ namespace OpenSim.Region.Framework.Scenes
1820 //pos.Z -= 0.25F; 1881 //pos.Z -= 0.25F;
1821 1882
1822 } 1883 }
1823
1824 return pos;
1825 } 1884 }
1826 else 1885 else
1827 { 1886 {
1828 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1887 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1829
1830 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1888 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1831 1889
1832 // Un-comment the following line to print the raytrace results to the console. 1890 // Un-comment the following line to print the raytrace results to the console.
@@ -1835,13 +1893,12 @@ namespace OpenSim.Region.Framework.Scenes
1835 if (ei.HitTF) 1893 if (ei.HitTF)
1836 { 1894 {
1837 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1895 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1838 } else 1896 }
1897 else
1839 { 1898 {
1840 // fall back to our stupid functionality 1899 // fall back to our stupid functionality
1841 pos = RayEnd; 1900 pos = RayEnd;
1842 } 1901 }
1843
1844 return pos;
1845 } 1902 }
1846 } 1903 }
1847 else 1904 else
@@ -1852,8 +1909,12 @@ namespace OpenSim.Region.Framework.Scenes
1852 //increase height so its above the ground. 1909 //increase height so its above the ground.
1853 //should be getting the normal of the ground at the rez point and using that? 1910 //should be getting the normal of the ground at the rez point and using that?
1854 pos.Z += scale.Z / 2f; 1911 pos.Z += scale.Z / 2f;
1855 return pos; 1912// return pos;
1856 } 1913 }
1914
1915 // check against posible water intercept
1916 if (wpos.Z > pos.Z) pos = wpos;
1917 return pos;
1857 } 1918 }
1858 1919
1859 1920
@@ -1937,7 +1998,10 @@ namespace OpenSim.Region.Framework.Scenes
1937 public bool AddRestoredSceneObject( 1998 public bool AddRestoredSceneObject(
1938 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 1999 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
1939 { 2000 {
1940 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2001 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
2002 if (result)
2003 sceneObject.IsDeleted = false;
2004 return result;
1941 } 2005 }
1942 2006
1943 /// <summary> 2007 /// <summary>
@@ -2029,6 +2093,15 @@ namespace OpenSim.Region.Framework.Scenes
2029 /// </summary> 2093 /// </summary>
2030 public void DeleteAllSceneObjects() 2094 public void DeleteAllSceneObjects()
2031 { 2095 {
2096 DeleteAllSceneObjects(false);
2097 }
2098
2099 /// <summary>
2100 /// Delete every object from the scene. This does not include attachments worn by avatars.
2101 /// </summary>
2102 public void DeleteAllSceneObjects(bool exceptNoCopy)
2103 {
2104 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2032 lock (Entities) 2105 lock (Entities)
2033 { 2106 {
2034 EntityBase[] entities = Entities.GetEntities(); 2107 EntityBase[] entities = Entities.GetEntities();
@@ -2037,11 +2110,24 @@ namespace OpenSim.Region.Framework.Scenes
2037 if (e is SceneObjectGroup) 2110 if (e is SceneObjectGroup)
2038 { 2111 {
2039 SceneObjectGroup sog = (SceneObjectGroup)e; 2112 SceneObjectGroup sog = (SceneObjectGroup)e;
2040 if (!sog.IsAttachment) 2113 if (sog != null && !sog.IsAttachment)
2041 DeleteSceneObject((SceneObjectGroup)e, false); 2114 {
2115 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2116 {
2117 DeleteSceneObject((SceneObjectGroup)e, false);
2118 }
2119 else
2120 {
2121 toReturn.Add((SceneObjectGroup)e);
2122 }
2123 }
2042 } 2124 }
2043 } 2125 }
2044 } 2126 }
2127 if (toReturn.Count > 0)
2128 {
2129 returnObjects(toReturn.ToArray(), UUID.Zero);
2130 }
2045 } 2131 }
2046 2132
2047 /// <summary> 2133 /// <summary>
@@ -2082,6 +2168,8 @@ namespace OpenSim.Region.Framework.Scenes
2082 } 2168 }
2083 2169
2084 group.DeleteGroupFromScene(silent); 2170 group.DeleteGroupFromScene(silent);
2171 if (!silent)
2172 SendKillObject(new List<uint>() { group.LocalId });
2085 2173
2086// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2174// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2087 } 2175 }
@@ -2371,6 +2459,8 @@ namespace OpenSim.Region.Framework.Scenes
2371 2459
2372 if (newPosition != Vector3.Zero) 2460 if (newPosition != Vector3.Zero)
2373 newObject.RootPart.GroupPosition = newPosition; 2461 newObject.RootPart.GroupPosition = newPosition;
2462 if (newObject.RootPart.KeyframeMotion != null)
2463 newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2374 2464
2375 if (!AddSceneObject(newObject)) 2465 if (!AddSceneObject(newObject))
2376 { 2466 {
@@ -2439,10 +2529,17 @@ namespace OpenSim.Region.Framework.Scenes
2439 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2529 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2440 public bool AddSceneObject(SceneObjectGroup sceneObject) 2530 public bool AddSceneObject(SceneObjectGroup sceneObject)
2441 { 2531 {
2532 if (sceneObject.OwnerID == UUID.Zero)
2533 {
2534 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2535 return false;
2536 }
2537
2442 // If the user is banned, we won't let any of their objects 2538 // If the user is banned, we won't let any of their objects
2443 // enter. Period. 2539 // enter. Period.
2444 // 2540 //
2445 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2541 int flags = GetUserFlags(sceneObject.OwnerID);
2542 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2446 { 2543 {
2447 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2544 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2448 2545
@@ -2488,12 +2585,23 @@ namespace OpenSim.Region.Framework.Scenes
2488 } 2585 }
2489 else 2586 else
2490 { 2587 {
2588 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2491 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2589 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2492 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2590 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2493 } 2591 }
2592 if (sceneObject.OwnerID == UUID.Zero)
2593 {
2594 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2595 return false;
2596 }
2494 } 2597 }
2495 else 2598 else
2496 { 2599 {
2600 if (sceneObject.OwnerID == UUID.Zero)
2601 {
2602 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2603 return false;
2604 }
2497 AddRestoredSceneObject(sceneObject, true, false); 2605 AddRestoredSceneObject(sceneObject, true, false);
2498 2606
2499 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2607 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2522,6 +2630,24 @@ namespace OpenSim.Region.Framework.Scenes
2522 return 2; // StateSource.PrimCrossing 2630 return 2; // StateSource.PrimCrossing
2523 } 2631 }
2524 2632
2633 public int GetUserFlags(UUID user)
2634 {
2635 //Unfortunately the SP approach means that the value is cached until region is restarted
2636 /*
2637 ScenePresence sp;
2638 if (TryGetScenePresence(user, out sp))
2639 {
2640 return sp.UserFlags;
2641 }
2642 else
2643 {
2644 */
2645 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2646 if (uac == null)
2647 return 0;
2648 return uac.UserFlags;
2649 //}
2650 }
2525 #endregion 2651 #endregion
2526 2652
2527 #region Add/Remove Avatar Methods 2653 #region Add/Remove Avatar Methods
@@ -2536,6 +2662,7 @@ namespace OpenSim.Region.Framework.Scenes
2536 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2662 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2537 2663
2538 CheckHeartbeat(); 2664 CheckHeartbeat();
2665 ScenePresence presence;
2539 2666
2540 ScenePresence sp = GetScenePresence(client.AgentId); 2667 ScenePresence sp = GetScenePresence(client.AgentId);
2541 2668
@@ -2584,7 +2711,13 @@ namespace OpenSim.Region.Framework.Scenes
2584 2711
2585 EventManager.TriggerOnNewClient(client); 2712 EventManager.TriggerOnNewClient(client);
2586 if (vialogin) 2713 if (vialogin)
2714 {
2587 EventManager.TriggerOnClientLogin(client); 2715 EventManager.TriggerOnClientLogin(client);
2716 // Send initial parcel data
2717 Vector3 pos = sp.AbsolutePosition;
2718 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2719 land.SendLandUpdateToClient(client);
2720 }
2588 2721
2589 return sp; 2722 return sp;
2590 } 2723 }
@@ -2674,19 +2807,12 @@ namespace OpenSim.Region.Framework.Scenes
2674 // and the scene presence and the client, if they exist 2807 // and the scene presence and the client, if they exist
2675 try 2808 try
2676 { 2809 {
2677 // We need to wait for the client to make UDP contact first. 2810 ScenePresence sp = GetScenePresence(agentID);
2678 // It's the UDP contact that creates the scene presence 2811 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2679 ScenePresence sp = WaitGetScenePresence(agentID); 2812
2680 if (sp != null) 2813 if (sp != null)
2681 {
2682 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2683
2684 sp.ControllingClient.Close(); 2814 sp.ControllingClient.Close();
2685 } 2815
2686 else
2687 {
2688 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2689 }
2690 // BANG! SLASH! 2816 // BANG! SLASH!
2691 m_authenticateHandler.RemoveCircuit(agentID); 2817 m_authenticateHandler.RemoveCircuit(agentID);
2692 2818
@@ -2731,6 +2857,8 @@ namespace OpenSim.Region.Framework.Scenes
2731 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 2857 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
2732 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 2858 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
2733 2859
2860 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
2861
2734 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 2862 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
2735 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 2863 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
2736 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 2864 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -2787,6 +2915,7 @@ namespace OpenSim.Region.Framework.Scenes
2787 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 2915 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2788 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 2916 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2789 client.OnCopyInventoryItem += CopyInventoryItem; 2917 client.OnCopyInventoryItem += CopyInventoryItem;
2918 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2790 client.OnMoveInventoryItem += MoveInventoryItem; 2919 client.OnMoveInventoryItem += MoveInventoryItem;
2791 client.OnRemoveInventoryItem += RemoveInventoryItem; 2920 client.OnRemoveInventoryItem += RemoveInventoryItem;
2792 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 2921 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2858,6 +2987,8 @@ namespace OpenSim.Region.Framework.Scenes
2858 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 2987 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
2859 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 2988 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
2860 2989
2990 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
2991
2861 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 2992 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2862 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 2993 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2863 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 2994 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -2960,15 +3091,16 @@ namespace OpenSim.Region.Framework.Scenes
2960 /// </summary> 3091 /// </summary>
2961 /// <param name="agentId">The avatar's Unique ID</param> 3092 /// <param name="agentId">The avatar's Unique ID</param>
2962 /// <param name="client">The IClientAPI for the client</param> 3093 /// <param name="client">The IClientAPI for the client</param>
2963 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3094 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
2964 { 3095 {
2965 if (m_teleportModule != null) 3096 if (m_teleportModule != null)
2966 m_teleportModule.TeleportHome(agentId, client); 3097 return m_teleportModule.TeleportHome(agentId, client);
2967 else 3098 else
2968 { 3099 {
2969 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3100 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
2970 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3101 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
2971 } 3102 }
3103 return false;
2972 } 3104 }
2973 3105
2974 /// <summary> 3106 /// <summary>
@@ -3078,6 +3210,16 @@ namespace OpenSim.Region.Framework.Scenes
3078 /// <param name="flags"></param> 3210 /// <param name="flags"></param>
3079 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3211 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3080 { 3212 {
3213 //Add half the avatar's height so that the user doesn't fall through prims
3214 ScenePresence presence;
3215 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3216 {
3217 if (presence.Appearance != null)
3218 {
3219 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3220 }
3221 }
3222
3081 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3223 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3082 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3224 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3083 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3225 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3146,8 +3288,9 @@ namespace OpenSim.Region.Framework.Scenes
3146 regions.Remove(RegionInfo.RegionHandle); 3288 regions.Remove(RegionInfo.RegionHandle);
3147 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3289 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3148 } 3290 }
3149 3291 m_log.Debug("[Scene] Beginning ClientClosed");
3150 m_eventManager.TriggerClientClosed(agentID, this); 3292 m_eventManager.TriggerClientClosed(agentID, this);
3293 m_log.Debug("[Scene] Finished ClientClosed");
3151 } 3294 }
3152 catch (NullReferenceException) 3295 catch (NullReferenceException)
3153 { 3296 {
@@ -3209,9 +3352,10 @@ namespace OpenSim.Region.Framework.Scenes
3209 { 3352 {
3210 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3353 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3211 } 3354 }
3212 3355 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3213 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3356 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3214// CleanDroppedAttachments(); 3357// CleanDroppedAttachments();
3358 m_log.Debug("[Scene] The avatar has left the building");
3215 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3359 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3216 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3360 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3217 } 3361 }
@@ -3333,13 +3477,16 @@ namespace OpenSim.Region.Framework.Scenes
3333 sp = null; 3477 sp = null;
3334 } 3478 }
3335 3479
3336 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3337 3480
3338 //On login test land permisions 3481 //On login test land permisions
3339 if (vialogin) 3482 if (vialogin)
3340 { 3483 {
3341 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3484 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3485 if (cache != null)
3486 cache.Remove(agent.firstname + " " + agent.lastname);
3487 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3342 { 3488 {
3489 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3343 return false; 3490 return false;
3344 } 3491 }
3345 } 3492 }
@@ -3363,8 +3510,13 @@ namespace OpenSim.Region.Framework.Scenes
3363 3510
3364 try 3511 try
3365 { 3512 {
3366 if (!AuthorizeUser(agent, out reason)) 3513 // Always check estate if this is a login. Always
3367 return false; 3514 // check if banned regions are to be blacked out.
3515 if (vialogin || (!m_seeIntoBannedRegion))
3516 {
3517 if (!AuthorizeUser(agent, out reason))
3518 return false;
3519 }
3368 } 3520 }
3369 catch (Exception e) 3521 catch (Exception e)
3370 { 3522 {
@@ -3490,6 +3642,8 @@ namespace OpenSim.Region.Framework.Scenes
3490 } 3642 }
3491 3643
3492 // Honor parcel landing type and position. 3644 // Honor parcel landing type and position.
3645 /*
3646 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3493 if (land != null) 3647 if (land != null)
3494 { 3648 {
3495 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3649 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3497,26 +3651,34 @@ namespace OpenSim.Region.Framework.Scenes
3497 agent.startpos = land.LandData.UserLocation; 3651 agent.startpos = land.LandData.UserLocation;
3498 } 3652 }
3499 } 3653 }
3654 */// This is now handled properly in ScenePresence.MakeRootAgent
3500 } 3655 }
3501 3656
3502 return true; 3657 return true;
3503 } 3658 }
3504 3659
3505 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3660 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3506 { 3661 {
3507 3662 reason = String.Empty;
3508 bool banned = land.IsBannedFromLand(agent.AgentID); 3663 if (Permissions.IsGod(agentID))
3509 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3664 return true;
3665
3666 ILandObject land = LandChannel.GetLandObject(posX, posY);
3667 if (land == null)
3668 return false;
3669
3670 bool banned = land.IsBannedFromLand(agentID);
3671 bool restricted = land.IsRestrictedFromLand(agentID);
3510 3672
3511 if (banned || restricted) 3673 if (banned || restricted)
3512 { 3674 {
3513 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3675 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3514 if (nearestParcel != null) 3676 if (nearestParcel != null)
3515 { 3677 {
3516 //Move agent to nearest allowed 3678 //Move agent to nearest allowed
3517 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3679 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3518 agent.startpos.X = newPosition.X; 3680 posX = newPosition.X;
3519 agent.startpos.Y = newPosition.Y; 3681 posY = newPosition.Y;
3520 } 3682 }
3521 else 3683 else
3522 { 3684 {
@@ -3578,7 +3740,7 @@ namespace OpenSim.Region.Framework.Scenes
3578 3740
3579 if (!m_strictAccessControl) return true; 3741 if (!m_strictAccessControl) return true;
3580 if (Permissions.IsGod(agent.AgentID)) return true; 3742 if (Permissions.IsGod(agent.AgentID)) return true;
3581 3743
3582 if (AuthorizationService != null) 3744 if (AuthorizationService != null)
3583 { 3745 {
3584 if (!AuthorizationService.IsAuthorizedForRegion( 3746 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3593,7 +3755,7 @@ namespace OpenSim.Region.Framework.Scenes
3593 3755
3594 if (m_regInfo.EstateSettings != null) 3756 if (m_regInfo.EstateSettings != null)
3595 { 3757 {
3596 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3758 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3597 { 3759 {
3598 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3760 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3599 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3761 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3785,6 +3947,13 @@ namespace OpenSim.Region.Framework.Scenes
3785 3947
3786 // We have to wait until the viewer contacts this region after receiving EAC. 3948 // We have to wait until the viewer contacts this region after receiving EAC.
3787 // That calls AddNewClient, which finally creates the ScenePresence 3949 // That calls AddNewClient, which finally creates the ScenePresence
3950 int flags = GetUserFlags(cAgentData.AgentID);
3951 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
3952 {
3953 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
3954 return false;
3955 }
3956
3788 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 3957 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3789 if (nearestParcel == null) 3958 if (nearestParcel == null)
3790 { 3959 {
@@ -3866,12 +4035,22 @@ namespace OpenSim.Region.Framework.Scenes
3866 return false; 4035 return false;
3867 } 4036 }
3868 4037
4038 public bool IncomingCloseAgent(UUID agentID)
4039 {
4040 return IncomingCloseAgent(agentID, false);
4041 }
4042
4043 public bool IncomingCloseChildAgent(UUID agentID)
4044 {
4045 return IncomingCloseAgent(agentID, true);
4046 }
4047
3869 /// <summary> 4048 /// <summary>
3870 /// Tell a single agent to disconnect from the region. 4049 /// Tell a single agent to disconnect from the region.
3871 /// </summary> 4050 /// </summary>
3872 /// <param name="regionHandle"></param>
3873 /// <param name="agentID"></param> 4051 /// <param name="agentID"></param>
3874 public bool IncomingCloseAgent(UUID agentID) 4052 /// <param name="childOnly"></param>
4053 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3875 { 4054 {
3876 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4055 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3877 4056
@@ -3883,7 +4062,7 @@ namespace OpenSim.Region.Framework.Scenes
3883 { 4062 {
3884 m_sceneGraph.removeUserCount(false); 4063 m_sceneGraph.removeUserCount(false);
3885 } 4064 }
3886 else 4065 else if (!childOnly)
3887 { 4066 {
3888 m_sceneGraph.removeUserCount(true); 4067 m_sceneGraph.removeUserCount(true);
3889 } 4068 }
@@ -3899,9 +4078,12 @@ namespace OpenSim.Region.Framework.Scenes
3899 } 4078 }
3900 else 4079 else
3901 presence.ControllingClient.SendShutdownConnectionNotice(); 4080 presence.ControllingClient.SendShutdownConnectionNotice();
4081 presence.ControllingClient.Close(false);
4082 }
4083 else if (!childOnly)
4084 {
4085 presence.ControllingClient.Close(true);
3902 } 4086 }
3903
3904 presence.ControllingClient.Close();
3905 return true; 4087 return true;
3906 } 4088 }
3907 4089
@@ -4483,34 +4665,78 @@ namespace OpenSim.Region.Framework.Scenes
4483 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4665 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4484 } 4666 }
4485 4667
4486 public int GetHealth() 4668 public int GetHealth(out int flags, out string message)
4487 { 4669 {
4488 // Returns: 4670 // Returns:
4489 // 1 = sim is up and accepting http requests. The heartbeat has 4671 // 1 = sim is up and accepting http requests. The heartbeat has
4490 // stopped and the sim is probably locked up, but a remote 4672 // stopped and the sim is probably locked up, but a remote
4491 // admin restart may succeed 4673 // admin restart may succeed
4492 // 4674 //
4493 // 2 = Sim is up and the heartbeat is running. The sim is likely 4675 // 2 = Sim is up and the heartbeat is running. The sim is likely
4494 // usable for people within and logins _may_ work 4676 // usable for people within
4677 //
4678 // 3 = Sim is up and one packet thread is running. Sim is
4679 // unstable and will not accept new logins
4680 //
4681 // 4 = Sim is up and both packet threads are running. Sim is
4682 // likely usable
4495 // 4683 //
4496 // 3 = We have seen a new user enter within the past 4 minutes 4684 // 5 = We have seen a new user enter within the past 4 minutes
4497 // which can be seen as positive confirmation of sim health 4685 // which can be seen as positive confirmation of sim health
4498 // 4686 //
4687
4688 flags = 0;
4689 message = String.Empty;
4690
4691 CheckHeartbeat();
4692
4693 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4694 {
4695 // We're still starting
4696 // 0 means "in startup", it can't happen another way, since
4697 // to get here, we must be able to accept http connections
4698 return 0;
4699 }
4700
4499 int health=1; // Start at 1, means we're up 4701 int health=1; // Start at 1, means we're up
4500 4702
4501 if ((Util.EnvironmentTickCountSubtract(m_lastUpdate)) < 1000) 4703 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) < 1000)
4704 {
4502 health+=1; 4705 health+=1;
4706 flags |= 1;
4707 }
4708
4709 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4710 {
4711 health+=1;
4712 flags |= 2;
4713 }
4714
4715 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4716 {
4717 health+=1;
4718 flags |= 4;
4719 }
4503 else 4720 else
4721 {
4722int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4723System.Diagnostics.Process proc = new System.Diagnostics.Process();
4724proc.EnableRaisingEvents=false;
4725proc.StartInfo.FileName = "/bin/kill";
4726proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4727proc.Start();
4728proc.WaitForExit();
4729Thread.Sleep(1000);
4730Environment.Exit(1);
4731 }
4732
4733 if (flags != 7)
4504 return health; 4734 return health;
4505 4735
4506 // A login in the last 4 mins? We can't be doing too badly 4736 // A login in the last 4 mins? We can't be doing too badly
4507 // 4737 //
4508 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4738 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4509 health++; 4739 health++;
4510 else
4511 return health;
4512
4513 CheckHeartbeat();
4514 4740
4515 return health; 4741 return health;
4516 } 4742 }
@@ -4599,7 +4825,7 @@ namespace OpenSim.Region.Framework.Scenes
4599 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 4825 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
4600 if (wasUsingPhysics) 4826 if (wasUsingPhysics)
4601 { 4827 {
4602 jointProxyObject.UpdatePrimFlags(false, false, true, false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock 4828 jointProxyObject.UpdatePrimFlags(false, false, true, false,false); // FIXME: possible deadlock here; check to make sure all the scene alterations set into motion here won't deadlock
4603 } 4829 }
4604 } 4830 }
4605 4831
@@ -4703,7 +4929,7 @@ namespace OpenSim.Region.Framework.Scenes
4703 if (m_firstHeartbeat) 4929 if (m_firstHeartbeat)
4704 return; 4930 return;
4705 4931
4706 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 2000) 4932 if (Util.EnvironmentTickCountSubtract(m_lastUpdate) > 5000)
4707 StartTimer(); 4933 StartTimer();
4708 } 4934 }
4709 4935
@@ -4717,9 +4943,14 @@ namespace OpenSim.Region.Framework.Scenes
4717 get { return m_allowScriptCrossings; } 4943 get { return m_allowScriptCrossings; }
4718 } 4944 }
4719 4945
4720 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 4946 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
4721 { 4947 {
4722 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 4948 return GetNearestAllowedPosition(avatar, null);
4949 }
4950
4951 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
4952 {
4953 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4723 4954
4724 if (nearestParcel != null) 4955 if (nearestParcel != null)
4725 { 4956 {
@@ -4728,10 +4959,7 @@ namespace OpenSim.Region.Framework.Scenes
4728 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 4959 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4729 if (nearestPoint != null) 4960 if (nearestPoint != null)
4730 { 4961 {
4731// m_log.DebugFormat( 4962 Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
4732// "[SCENE]: Found a sane previous position based on velocity for {0}, sending them to {1} in {2}",
4733// avatar.Name, nearestPoint, nearestParcel.LandData.Name);
4734
4735 return nearestPoint.Value; 4963 return nearestPoint.Value;
4736 } 4964 }
4737 4965
@@ -4741,17 +4969,20 @@ namespace OpenSim.Region.Framework.Scenes
4741 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 4969 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4742 if (nearestPoint != null) 4970 if (nearestPoint != null)
4743 { 4971 {
4744// m_log.DebugFormat( 4972 Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString());
4745// "[SCENE]: {0} had a zero velocity, sending them to {1}", avatar.Name, nearestPoint);
4746
4747 return nearestPoint.Value; 4973 return nearestPoint.Value;
4748 } 4974 }
4749 4975
4750 //Ultimate backup if we have no idea where they are 4976 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
4751// m_log.DebugFormat( 4977 if (dest != excludeParcel)
4752// "[SCENE]: No idea where {0} is, sending them to {1}", avatar.Name, avatar.lastKnownAllowedPosition); 4978 {
4979 // Ultimate backup if we have no idea where they are and
4980 // the last allowed position was in another parcel
4981 Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
4982 return avatar.lastKnownAllowedPosition;
4983 }
4753 4984
4754 return avatar.lastKnownAllowedPosition; 4985 // else fall through to region edge
4755 } 4986 }
4756 4987
4757 //Go to the edge, this happens in teleporting to a region with no available parcels 4988 //Go to the edge, this happens in teleporting to a region with no available parcels
@@ -4785,13 +5016,18 @@ namespace OpenSim.Region.Framework.Scenes
4785 5016
4786 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 5017 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4787 { 5018 {
5019 return GetNearestAllowedParcel(avatarId, x, y, null);
5020 }
5021
5022 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
5023 {
4788 List<ILandObject> all = AllParcels(); 5024 List<ILandObject> all = AllParcels();
4789 float minParcelDistance = float.MaxValue; 5025 float minParcelDistance = float.MaxValue;
4790 ILandObject nearestParcel = null; 5026 ILandObject nearestParcel = null;
4791 5027
4792 foreach (var parcel in all) 5028 foreach (var parcel in all)
4793 { 5029 {
4794 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 5030 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4795 { 5031 {
4796 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 5032 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4797 if (parcelDistance < minParcelDistance) 5033 if (parcelDistance < minParcelDistance)
@@ -5033,7 +5269,55 @@ namespace OpenSim.Region.Framework.Scenes
5033 mapModule.GenerateMaptile(); 5269 mapModule.GenerateMaptile();
5034 } 5270 }
5035 5271
5036 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5272// public void CleanDroppedAttachments()
5273// {
5274// List<SceneObjectGroup> objectsToDelete =
5275// new List<SceneObjectGroup>();
5276//
5277// lock (m_cleaningAttachments)
5278// {
5279// ForEachSOG(delegate (SceneObjectGroup grp)
5280// {
5281// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5282// {
5283// UUID agentID = grp.OwnerID;
5284// if (agentID == UUID.Zero)
5285// {
5286// objectsToDelete.Add(grp);
5287// return;
5288// }
5289//
5290// ScenePresence sp = GetScenePresence(agentID);
5291// if (sp == null)
5292// {
5293// objectsToDelete.Add(grp);
5294// return;
5295// }
5296// }
5297// });
5298// }
5299//
5300// foreach (SceneObjectGroup grp in objectsToDelete)
5301// {
5302// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5303// DeleteSceneObject(grp, true);
5304// }
5305// }
5306
5307 public void ThreadAlive(int threadCode)
5308 {
5309 switch(threadCode)
5310 {
5311 case 1: // Incoming
5312 m_lastIncoming = Util.EnvironmentTickCount();
5313 break;
5314 case 2: // Incoming
5315 m_lastOutgoing = Util.EnvironmentTickCount();
5316 break;
5317 }
5318 }
5319
5320 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5037 { 5321 {
5038 RegenerateMaptile(); 5322 RegenerateMaptile();
5039 5323
@@ -5052,6 +5336,14 @@ namespace OpenSim.Region.Framework.Scenes
5052 // child agent creation, thereby emulating the SL behavior. 5336 // child agent creation, thereby emulating the SL behavior.
5053 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5337 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5054 { 5338 {
5339 reason = "You are banned from the region";
5340
5341 if (Permissions.IsGod(agentID))
5342 {
5343 reason = String.Empty;
5344 return true;
5345 }
5346
5055 int num = m_sceneGraph.GetNumberOfScenePresences(); 5347 int num = m_sceneGraph.GetNumberOfScenePresences();
5056 5348
5057 if (num >= RegionInfo.RegionSettings.AgentLimit) 5349 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5063,6 +5355,41 @@ namespace OpenSim.Region.Framework.Scenes
5063 } 5355 }
5064 } 5356 }
5065 5357
5358 ScenePresence presence = GetScenePresence(agentID);
5359 IClientAPI client = null;
5360 AgentCircuitData aCircuit = null;
5361
5362 if (presence != null)
5363 {
5364 client = presence.ControllingClient;
5365 if (client != null)
5366 aCircuit = client.RequestClientInfo();
5367 }
5368
5369 // We may be called before there is a presence or a client.
5370 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5371 if (client == null)
5372 {
5373 aCircuit = new AgentCircuitData();
5374 aCircuit.AgentID = agentID;
5375 aCircuit.firstname = String.Empty;
5376 aCircuit.lastname = String.Empty;
5377 }
5378
5379 try
5380 {
5381 if (!AuthorizeUser(aCircuit, out reason))
5382 {
5383 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5384 return false;
5385 }
5386 }
5387 catch (Exception e)
5388 {
5389 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5390 return false;
5391 }
5392
5066 if (position == Vector3.Zero) // Teleport 5393 if (position == Vector3.Zero) // Teleport
5067 { 5394 {
5068 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5395 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5091,13 +5418,46 @@ namespace OpenSim.Region.Framework.Scenes
5091 } 5418 }
5092 } 5419 }
5093 } 5420 }
5421
5422 float posX = 128.0f;
5423 float posY = 128.0f;
5424
5425 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5426 {
5427 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5428 return false;
5429 }
5430 }
5431 else // Walking
5432 {
5433 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5434 if (land == null)
5435 return false;
5436
5437 bool banned = land.IsBannedFromLand(agentID);
5438 bool restricted = land.IsRestrictedFromLand(agentID);
5439
5440 if (banned || restricted)
5441 return false;
5094 } 5442 }
5095 5443
5096 reason = String.Empty; 5444 reason = String.Empty;
5097 return true; 5445 return true;
5098 } 5446 }
5099 5447
5100 /// <summary> 5448 public void StartTimerWatchdog()
5449 {
5450 m_timerWatchdog.Interval = 1000;
5451 m_timerWatchdog.Elapsed += TimerWatchdog;
5452 m_timerWatchdog.AutoReset = true;
5453 m_timerWatchdog.Start();
5454 }
5455
5456 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5457 {
5458 CheckHeartbeat();
5459 }
5460
5101 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5461 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5102 /// autopilot that moves an avatar to a sit target!. 5462 /// autopilot that moves an avatar to a sit target!.
5103 /// </summary> 5463 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 9c6b884..9b8a3ae 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 4d98f00..b806d91 100644
--- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs
@@ -88,7 +88,7 @@ namespace OpenSim.Region.Framework.Scenes
88 88
89 if (neighbour != null) 89 if (neighbour != null)
90 { 90 {
91 m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize); 91 // m_log.DebugFormat("[INTERGRID]: Successfully informed neighbour {0}-{1} that I'm here", x / Constants.RegionSize, y / Constants.RegionSize);
92 m_scene.EventManager.TriggerOnRegionUp(neighbour); 92 m_scene.EventManager.TriggerOnRegionUp(neighbour);
93 } 93 }
94 else 94 else
@@ -102,7 +102,7 @@ namespace OpenSim.Region.Framework.Scenes
102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); 102 //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName);
103 103
104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); 104 List<GridRegion> neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID);
105 m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); 105 //m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count);
106 foreach (GridRegion n in neighbours) 106 foreach (GridRegion n in neighbours)
107 { 107 {
108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; 108 InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync;
@@ -180,10 +180,13 @@ namespace OpenSim.Region.Framework.Scenes
180 } 180 }
181 } 181 }
182 182
183 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
184
183 /// <summary> 185 /// <summary>
184 /// Closes a child agent on a given region 186 /// This Closes child agents on neighboring regions
187 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
185 /// </summary> 188 /// </summary>
186 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 189 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
187 { 190 {
188 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 191 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
189 192
@@ -192,31 +195,29 @@ namespace OpenSim.Region.Framework.Scenes
192 Utils.LongToUInts(regionHandle, out x, out y); 195 Utils.LongToUInts(regionHandle, out x, out y);
193 196
194 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 197 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
198 m_scene.SimulationService.CloseChildAgent(destination, agentID);
199 }
195 200
196 m_log.DebugFormat( 201 private void SendCloseChildAgentCompleted(IAsyncResult iar)
197 "[INTERGRID]: Sending close agent {0} to region at {1}-{2}", 202 {
198 agentID, destination.RegionCoordX, destination.RegionCoordY); 203 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
199 204 icon.EndInvoke(iar);
200 m_scene.SimulationService.CloseAgent(destination, agentID);
201 } 205 }
202 206
203 /// <summary>
204 /// Closes a child agents in a collection of regions. Does so asynchronously
205 /// so that the caller doesn't wait.
206 /// </summary>
207 /// <param name="agentID"></param>
208 /// <param name="regionslst"></param>
209 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 207 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
210 { 208 {
211 foreach (ulong handle in regionslst) 209 foreach (ulong handle in regionslst)
212 { 210 {
213 SendCloseChildAgent(agentID, handle); 211 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
212 d.BeginInvoke(agentID, handle,
213 SendCloseChildAgentCompleted,
214 d);
214 } 215 }
215 } 216 }
216 217
217 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 218 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
218 { 219 {
219 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 220 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
220 } 221 }
221 } 222 }
222} \ No newline at end of file 223}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 5c542d6..ccc3f32 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -41,6 +41,12 @@ namespace OpenSim.Region.Framework.Scenes
41{ 41{
42 public delegate void PhysicsCrash(); 42 public delegate void PhysicsCrash();
43 43
44 public delegate void AttachToBackupDelegate(SceneObjectGroup sog);
45
46 public delegate void DetachFromBackupDelegate(SceneObjectGroup sog);
47
48 public delegate void ChangedBackupDelegate(SceneObjectGroup sog);
49
44 /// <summary> 50 /// <summary>
45 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components 51 /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components
46 /// should be migrated out over time. 52 /// should be migrated out over time.
@@ -54,11 +60,15 @@ namespace OpenSim.Region.Framework.Scenes
54 protected internal event PhysicsCrash UnRecoverableError; 60 protected internal event PhysicsCrash UnRecoverableError;
55 private PhysicsCrash handlerPhysicsCrash = null; 61 private PhysicsCrash handlerPhysicsCrash = null;
56 62
63 public event AttachToBackupDelegate OnAttachToBackup;
64 public event DetachFromBackupDelegate OnDetachFromBackup;
65 public event ChangedBackupDelegate OnChangeBackup;
66
57 #endregion 67 #endregion
58 68
59 #region Fields 69 #region Fields
60 70
61 protected object m_presenceLock = new object(); 71 protected OpenMetaverse.ReaderWriterLockSlim m_scenePresencesLock = new OpenMetaverse.ReaderWriterLockSlim();
62 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>(); 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
63 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>(); 73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
64 74
@@ -120,13 +130,18 @@ namespace OpenSim.Region.Framework.Scenes
120 130
121 protected internal void Close() 131 protected internal void Close()
122 { 132 {
123 lock (m_presenceLock) 133 m_scenePresencesLock.EnterWriteLock();
134 try
124 { 135 {
125 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 136 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
126 List<ScenePresence> newlist = new List<ScenePresence>(); 137 List<ScenePresence> newlist = new List<ScenePresence>();
127 m_scenePresenceMap = newmap; 138 m_scenePresenceMap = newmap;
128 m_scenePresenceArray = newlist; 139 m_scenePresenceArray = newlist;
129 } 140 }
141 finally
142 {
143 m_scenePresencesLock.ExitWriteLock();
144 }
130 145
131 lock (SceneObjectGroupsByFullID) 146 lock (SceneObjectGroupsByFullID)
132 SceneObjectGroupsByFullID.Clear(); 147 SceneObjectGroupsByFullID.Clear();
@@ -247,6 +262,33 @@ namespace OpenSim.Region.Framework.Scenes
247 protected internal bool AddRestoredSceneObject( 262 protected internal bool AddRestoredSceneObject(
248 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 263 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
249 { 264 {
265 if (!m_parentScene.CombineRegions)
266 {
267 // KF: Check for out-of-region, move inside and make static.
268 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
269 sceneObject.RootPart.GroupPosition.Y,
270 sceneObject.RootPart.GroupPosition.Z);
271 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 ||
272 npos.X > Constants.RegionSize ||
273 npos.Y > Constants.RegionSize))
274 {
275 if (npos.X < 0.0) npos.X = 1.0f;
276 if (npos.Y < 0.0) npos.Y = 1.0f;
277 if (npos.Z < 0.0) npos.Z = 0.0f;
278 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
279 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
280
281 foreach (SceneObjectPart part in sceneObject.Parts)
282 {
283 part.GroupPosition = npos;
284 }
285 sceneObject.RootPart.Velocity = Vector3.Zero;
286 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
287 sceneObject.RootPart.Acceleration = Vector3.Zero;
288 sceneObject.RootPart.Velocity = Vector3.Zero;
289 }
290 }
291
250 if (attachToBackup && (!alreadyPersisted)) 292 if (attachToBackup && (!alreadyPersisted))
251 { 293 {
252 sceneObject.ForceInventoryPersistence(); 294 sceneObject.ForceInventoryPersistence();
@@ -336,6 +378,11 @@ namespace OpenSim.Region.Framework.Scenes
336 /// </returns> 378 /// </returns>
337 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 379 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
338 { 380 {
381 if (sceneObject == null)
382 {
383 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
384 return false;
385 }
339 if (sceneObject.UUID == UUID.Zero) 386 if (sceneObject.UUID == UUID.Zero)
340 { 387 {
341 m_log.ErrorFormat( 388 m_log.ErrorFormat(
@@ -470,6 +517,30 @@ namespace OpenSim.Region.Framework.Scenes
470 m_updateList[obj.UUID] = obj; 517 m_updateList[obj.UUID] = obj;
471 } 518 }
472 519
520 public void FireAttachToBackup(SceneObjectGroup obj)
521 {
522 if (OnAttachToBackup != null)
523 {
524 OnAttachToBackup(obj);
525 }
526 }
527
528 public void FireDetachFromBackup(SceneObjectGroup obj)
529 {
530 if (OnDetachFromBackup != null)
531 {
532 OnDetachFromBackup(obj);
533 }
534 }
535
536 public void FireChangeBackup(SceneObjectGroup obj)
537 {
538 if (OnChangeBackup != null)
539 {
540 OnChangeBackup(obj);
541 }
542 }
543
473 /// <summary> 544 /// <summary>
474 /// Process all pending updates 545 /// Process all pending updates
475 /// </summary> 546 /// </summary>
@@ -587,7 +658,8 @@ namespace OpenSim.Region.Framework.Scenes
587 658
588 Entities[presence.UUID] = presence; 659 Entities[presence.UUID] = presence;
589 660
590 lock (m_presenceLock) 661 m_scenePresencesLock.EnterWriteLock();
662 try
591 { 663 {
592 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 664 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
593 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 665 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -611,6 +683,10 @@ namespace OpenSim.Region.Framework.Scenes
611 m_scenePresenceMap = newmap; 683 m_scenePresenceMap = newmap;
612 m_scenePresenceArray = newlist; 684 m_scenePresenceArray = newlist;
613 } 685 }
686 finally
687 {
688 m_scenePresencesLock.ExitWriteLock();
689 }
614 } 690 }
615 691
616 /// <summary> 692 /// <summary>
@@ -625,7 +701,8 @@ namespace OpenSim.Region.Framework.Scenes
625 agentID); 701 agentID);
626 } 702 }
627 703
628 lock (m_presenceLock) 704 m_scenePresencesLock.EnterWriteLock();
705 try
629 { 706 {
630 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 707 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
631 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 708 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -647,6 +724,10 @@ namespace OpenSim.Region.Framework.Scenes
647 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 724 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
648 } 725 }
649 } 726 }
727 finally
728 {
729 m_scenePresencesLock.ExitWriteLock();
730 }
650 } 731 }
651 732
652 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 733 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1179,6 +1260,25 @@ namespace OpenSim.Region.Framework.Scenes
1179 1260
1180 #region Client Event handlers 1261 #region Client Event handlers
1181 1262
1263 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1264 {
1265 SceneObjectPart part = GetSceneObjectPart(localID);
1266 ObjectChangeData data = (ObjectChangeData)odata;
1267
1268 if (part != null)
1269 {
1270 SceneObjectGroup grp = part.ParentGroup;
1271 if (grp != null)
1272 {
1273 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1274 {
1275 part.StoreUndoState(data.change); // lets test only saving what we changed
1276 grp.doChangeObject(part, (ObjectChangeData)data);
1277 }
1278 }
1279 }
1280 }
1281
1182 /// <summary> 1282 /// <summary>
1183 /// Update the scale of an individual prim. 1283 /// Update the scale of an individual prim.
1184 /// </summary> 1284 /// </summary>
@@ -1193,7 +1293,17 @@ namespace OpenSim.Region.Framework.Scenes
1193 { 1293 {
1194 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1294 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1195 { 1295 {
1296 bool physbuild = false;
1297 if (part.ParentGroup.RootPart.PhysActor != null)
1298 {
1299 part.ParentGroup.RootPart.PhysActor.Building = true;
1300 physbuild = true;
1301 }
1302
1196 part.Resize(scale); 1303 part.Resize(scale);
1304
1305 if (physbuild)
1306 part.ParentGroup.RootPart.PhysActor.Building = false;
1197 } 1307 }
1198 } 1308 }
1199 } 1309 }
@@ -1205,7 +1315,17 @@ namespace OpenSim.Region.Framework.Scenes
1205 { 1315 {
1206 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1316 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1207 { 1317 {
1318 bool physbuild = false;
1319 if (group.RootPart.PhysActor != null)
1320 {
1321 group.RootPart.PhysActor.Building = true;
1322 physbuild = true;
1323 }
1324
1208 group.GroupResize(scale); 1325 group.GroupResize(scale);
1326
1327 if (physbuild)
1328 group.RootPart.PhysActor.Building = false;
1209 } 1329 }
1210 } 1330 }
1211 } 1331 }
@@ -1333,8 +1453,13 @@ namespace OpenSim.Region.Framework.Scenes
1333 { 1453 {
1334 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1454 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1335 { 1455 {
1336 if (m_parentScene.AttachmentsModule != null) 1456 // Set the new attachment point data in the object
1337 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1457 byte attachmentPoint = group.GetAttachmentPoint();
1458 group.UpdateGroupPosition(pos);
1459 group.IsAttachment = false;
1460 group.AbsolutePosition = group.RootPart.AttachedPos;
1461 group.AttachmentPoint = attachmentPoint;
1462 group.HasGroupChanged = true;
1338 } 1463 }
1339 else 1464 else
1340 { 1465 {
@@ -1382,7 +1507,7 @@ namespace OpenSim.Region.Framework.Scenes
1382 /// <param name="SetPhantom"></param> 1507 /// <param name="SetPhantom"></param>
1383 /// <param name="remoteClient"></param> 1508 /// <param name="remoteClient"></param>
1384 protected internal void UpdatePrimFlags( 1509 protected internal void UpdatePrimFlags(
1385 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) 1510 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient)
1386 { 1511 {
1387 SceneObjectGroup group = GetGroupByPrim(localID); 1512 SceneObjectGroup group = GetGroupByPrim(localID);
1388 if (group != null) 1513 if (group != null)
@@ -1390,7 +1515,18 @@ namespace OpenSim.Region.Framework.Scenes
1390 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1515 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1391 { 1516 {
1392 // VolumeDetect can't be set via UI and will always be off when a change is made there 1517 // VolumeDetect can't be set via UI and will always be off when a change is made there
1393 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); 1518 if (PhysData.PhysShapeType == PhysShapeType.invalid)
1519 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false);
1520 else
1521 {
1522 SceneObjectPart part = GetSceneObjectPart(localID);
1523 if (part != null)
1524 {
1525 part.UpdateExtraPhysics(PhysData);
1526 if (part.UpdatePhysRequired)
1527 remoteClient.SendPartPhysicsProprieties(part);
1528 }
1529 }
1394 } 1530 }
1395 } 1531 }
1396 } 1532 }
@@ -1534,6 +1670,7 @@ namespace OpenSim.Region.Framework.Scenes
1534 { 1670 {
1535 part.Material = Convert.ToByte(material); 1671 part.Material = Convert.ToByte(material);
1536 group.HasGroupChanged = true; 1672 group.HasGroupChanged = true;
1673 remoteClient.SendPartPhysicsProprieties(part);
1537 } 1674 }
1538 } 1675 }
1539 } 1676 }
@@ -1598,6 +1735,12 @@ namespace OpenSim.Region.Framework.Scenes
1598 /// <param name="childPrims"></param> 1735 /// <param name="childPrims"></param>
1599 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1736 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1600 { 1737 {
1738 if (root.KeyframeMotion != null)
1739 {
1740 root.KeyframeMotion.Stop();
1741 root.KeyframeMotion = null;
1742 }
1743
1601 SceneObjectGroup parentGroup = root.ParentGroup; 1744 SceneObjectGroup parentGroup = root.ParentGroup;
1602 if (parentGroup == null) return; 1745 if (parentGroup == null) return;
1603 1746
@@ -1606,8 +1749,11 @@ namespace OpenSim.Region.Framework.Scenes
1606 return; 1749 return;
1607 1750
1608 Monitor.Enter(m_updateLock); 1751 Monitor.Enter(m_updateLock);
1752
1609 try 1753 try
1610 { 1754 {
1755 parentGroup.areUpdatesSuspended = true;
1756
1611 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1757 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1612 1758
1613 // We do this in reverse to get the link order of the prims correct 1759 // We do this in reverse to get the link order of the prims correct
@@ -1622,9 +1768,13 @@ namespace OpenSim.Region.Framework.Scenes
1622 // Make sure no child prim is set for sale 1768 // Make sure no child prim is set for sale
1623 // So that, on delink, no prims are unwittingly 1769 // So that, on delink, no prims are unwittingly
1624 // left for sale and sold off 1770 // left for sale and sold off
1625 child.RootPart.ObjectSaleType = 0; 1771
1626 child.RootPart.SalePrice = 10; 1772 if (child != null)
1627 childGroups.Add(child); 1773 {
1774 child.RootPart.ObjectSaleType = 0;
1775 child.RootPart.SalePrice = 10;
1776 childGroups.Add(child);
1777 }
1628 } 1778 }
1629 1779
1630 foreach (SceneObjectGroup child in childGroups) 1780 foreach (SceneObjectGroup child in childGroups)
@@ -1651,6 +1801,16 @@ namespace OpenSim.Region.Framework.Scenes
1651 } 1801 }
1652 finally 1802 finally
1653 { 1803 {
1804 lock (SceneObjectGroupsByLocalPartID)
1805 {
1806 foreach (SceneObjectPart part in parentGroup.Parts)
1807 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1808 }
1809
1810 parentGroup.areUpdatesSuspended = false;
1811 parentGroup.HasGroupChanged = true;
1812 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1813 parentGroup.ScheduleGroupForFullUpdate();
1654 Monitor.Exit(m_updateLock); 1814 Monitor.Exit(m_updateLock);
1655 } 1815 }
1656 } 1816 }
@@ -1673,6 +1833,11 @@ namespace OpenSim.Region.Framework.Scenes
1673 { 1833 {
1674 if (part != null) 1834 if (part != null)
1675 { 1835 {
1836 if (part.KeyframeMotion != null)
1837 {
1838 part.KeyframeMotion.Stop();
1839 part.KeyframeMotion = null;
1840 }
1676 if (part.ParentGroup.PrimCount != 1) // Skip single 1841 if (part.ParentGroup.PrimCount != 1) // Skip single
1677 { 1842 {
1678 if (part.LinkNum < 2) // Root 1843 if (part.LinkNum < 2) // Root
@@ -1687,21 +1852,24 @@ namespace OpenSim.Region.Framework.Scenes
1687 1852
1688 SceneObjectGroup group = part.ParentGroup; 1853 SceneObjectGroup group = part.ParentGroup;
1689 if (!affectedGroups.Contains(group)) 1854 if (!affectedGroups.Contains(group))
1855 {
1856 group.areUpdatesSuspended = true;
1690 affectedGroups.Add(group); 1857 affectedGroups.Add(group);
1858 }
1691 } 1859 }
1692 } 1860 }
1693 } 1861 }
1694 1862
1695 foreach (SceneObjectPart child in childParts) 1863 if (childParts.Count > 0)
1696 { 1864 {
1697 // Unlink all child parts from their groups 1865 foreach (SceneObjectPart child in childParts)
1698 // 1866 {
1699 child.ParentGroup.DelinkFromGroup(child, true); 1867 // Unlink all child parts from their groups
1700 1868 //
1701 // These are not in affected groups and will not be 1869 child.ParentGroup.DelinkFromGroup(child, true);
1702 // handled further. Do the honors here. 1870 child.ParentGroup.HasGroupChanged = true;
1703 child.ParentGroup.HasGroupChanged = true; 1871 child.ParentGroup.ScheduleGroupForFullUpdate();
1704 child.ParentGroup.ScheduleGroupForFullUpdate(); 1872 }
1705 } 1873 }
1706 1874
1707 foreach (SceneObjectPart root in rootParts) 1875 foreach (SceneObjectPart root in rootParts)
@@ -1711,56 +1879,68 @@ namespace OpenSim.Region.Framework.Scenes
1711 // However, editing linked parts and unlinking may be different 1879 // However, editing linked parts and unlinking may be different
1712 // 1880 //
1713 SceneObjectGroup group = root.ParentGroup; 1881 SceneObjectGroup group = root.ParentGroup;
1882 group.areUpdatesSuspended = true;
1714 1883
1715 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1884 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1716 int numChildren = newSet.Count; 1885 int numChildren = newSet.Count;
1717 1886
1887 if (numChildren == 1)
1888 break;
1889
1718 // If there are prims left in a link set, but the root is 1890 // If there are prims left in a link set, but the root is
1719 // slated for unlink, we need to do this 1891 // slated for unlink, we need to do this
1892 // Unlink the remaining set
1720 // 1893 //
1721 if (numChildren != 1) 1894 bool sendEventsToRemainder = true;
1722 { 1895 if (numChildren > 1)
1723 // Unlink the remaining set 1896 sendEventsToRemainder = false;
1724 //
1725 bool sendEventsToRemainder = true;
1726 if (numChildren > 1)
1727 sendEventsToRemainder = false;
1728 1897
1729 foreach (SceneObjectPart p in newSet) 1898 foreach (SceneObjectPart p in newSet)
1899 {
1900 if (p != group.RootPart)
1730 { 1901 {
1731 if (p != group.RootPart) 1902 group.DelinkFromGroup(p, sendEventsToRemainder);
1732 group.DelinkFromGroup(p, sendEventsToRemainder); 1903 if (numChildren > 2)
1904 {
1905 p.ParentGroup.areUpdatesSuspended = true;
1906 }
1907 else
1908 {
1909 p.ParentGroup.HasGroupChanged = true;
1910 p.ParentGroup.ScheduleGroupForFullUpdate();
1911 }
1733 } 1912 }
1913 }
1914
1915 // If there is more than one prim remaining, we
1916 // need to re-link
1917 //
1918 if (numChildren > 2)
1919 {
1920 // Remove old root
1921 //
1922 if (newSet.Contains(root))
1923 newSet.Remove(root);
1734 1924
1735 // If there is more than one prim remaining, we 1925 // Preserve link ordering
1736 // need to re-link
1737 // 1926 //
1738 if (numChildren > 2) 1927 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1739 { 1928 {
1740 // Remove old root 1929 return a.LinkNum.CompareTo(b.LinkNum);
1741 // 1930 });
1742 if (newSet.Contains(root))
1743 newSet.Remove(root);
1744
1745 // Preserve link ordering
1746 //
1747 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1748 {
1749 return a.LinkNum.CompareTo(b.LinkNum);
1750 });
1751 1931
1752 // Determine new root 1932 // Determine new root
1753 // 1933 //
1754 SceneObjectPart newRoot = newSet[0]; 1934 SceneObjectPart newRoot = newSet[0];
1755 newSet.RemoveAt(0); 1935 newSet.RemoveAt(0);
1756 1936
1757 foreach (SceneObjectPart newChild in newSet) 1937 foreach (SceneObjectPart newChild in newSet)
1758 newChild.ClearUpdateSchedule(); 1938 newChild.ClearUpdateSchedule();
1759 1939
1760 LinkObjects(newRoot, newSet); 1940 newRoot.ParentGroup.areUpdatesSuspended = true;
1761 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1941 LinkObjects(newRoot, newSet);
1762 affectedGroups.Add(newRoot.ParentGroup); 1942 if (!affectedGroups.Contains(newRoot.ParentGroup))
1763 } 1943 affectedGroups.Add(newRoot.ParentGroup);
1764 } 1944 }
1765 } 1945 }
1766 1946
@@ -1768,8 +1948,14 @@ namespace OpenSim.Region.Framework.Scenes
1768 // 1948 //
1769 foreach (SceneObjectGroup g in affectedGroups) 1949 foreach (SceneObjectGroup g in affectedGroups)
1770 { 1950 {
1951 // Child prims that have been unlinked and deleted will
1952 // return unless the root is deleted. This will remove them
1953 // from the database. They will be rewritten immediately,
1954 // minus the rows for the unlinked child prims.
1955 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1771 g.TriggerScriptChangedEvent(Changed.LINK); 1956 g.TriggerScriptChangedEvent(Changed.LINK);
1772 g.HasGroupChanged = true; // Persist 1957 g.HasGroupChanged = true; // Persist
1958 g.areUpdatesSuspended = false;
1773 g.ScheduleGroupForFullUpdate(); 1959 g.ScheduleGroupForFullUpdate();
1774 } 1960 }
1775 } 1961 }
@@ -1871,9 +2057,6 @@ namespace OpenSim.Region.Framework.Scenes
1871 child.ApplyNextOwnerPermissions(); 2057 child.ApplyNextOwnerPermissions();
1872 } 2058 }
1873 } 2059 }
1874
1875 copy.RootPart.ObjectSaleType = 0;
1876 copy.RootPart.SalePrice = 10;
1877 } 2060 }
1878 2061
1879 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2062 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index d73a959..e4eaf3a 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -356,7 +356,7 @@ namespace OpenSim.Region.Framework.Scenes
356 356
357 public bool TrySetCurrentScene(UUID regionID) 357 public bool TrySetCurrentScene(UUID regionID)
358 { 358 {
359 m_log.Debug("Searching for Region: '" + regionID + "'"); 359// m_log.Debug("Searching for Region: '" + regionID + "'");
360 360
361 lock (m_localScenes) 361 lock (m_localScenes)
362 { 362 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index a73d9b6..f3660a5 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();
@@ -227,6 +223,11 @@ namespace OpenSim.Region.Framework.Scenes
227 223
228 public uint GetEffectivePermissions() 224 public uint GetEffectivePermissions()
229 { 225 {
226 return GetEffectivePermissions(false);
227 }
228
229 public uint GetEffectivePermissions(bool useBase)
230 {
230 uint perms=(uint)(PermissionMask.Modify | 231 uint perms=(uint)(PermissionMask.Modify |
231 PermissionMask.Copy | 232 PermissionMask.Copy |
232 PermissionMask.Move | 233 PermissionMask.Move |
@@ -238,7 +239,10 @@ namespace OpenSim.Region.Framework.Scenes
238 for (int i = 0; i < parts.Length; i++) 239 for (int i = 0; i < parts.Length; i++)
239 { 240 {
240 SceneObjectPart part = parts[i]; 241 SceneObjectPart part = parts[i];
241 ownerMask &= part.OwnerMask; 242 if (useBase)
243 ownerMask &= part.BaseMask;
244 else
245 ownerMask &= part.OwnerMask;
242 perms &= part.Inventory.MaskEffectivePermissions(); 246 perms &= part.Inventory.MaskEffectivePermissions();
243 } 247 }
244 248
@@ -380,6 +384,9 @@ namespace OpenSim.Region.Framework.Scenes
380 384
381 public void ResumeScripts() 385 public void ResumeScripts()
382 { 386 {
387 if (m_scene.RegionInfo.RegionSettings.DisableScripts)
388 return;
389
383 SceneObjectPart[] parts = m_parts.GetArray(); 390 SceneObjectPart[] parts = m_parts.GetArray();
384 for (int i = 0; i < parts.Length; i++) 391 for (int i = 0; i < parts.Length; i++)
385 parts[i].Inventory.ResumeScripts(); 392 parts[i].Inventory.ResumeScripts();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index afb5ccf..90ad098 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;
@@ -42,6 +43,7 @@ using OpenSim.Region.Framework.Scenes.Serialization;
42 43
43namespace OpenSim.Region.Framework.Scenes 44namespace OpenSim.Region.Framework.Scenes
44{ 45{
46
45 [Flags] 47 [Flags]
46 public enum scriptEvents 48 public enum scriptEvents
47 { 49 {
@@ -105,8 +107,29 @@ namespace OpenSim.Region.Framework.Scenes
105 /// since the group's last persistent backup 107 /// since the group's last persistent backup
106 /// </summary> 108 /// </summary>
107 private bool m_hasGroupChanged = false; 109 private bool m_hasGroupChanged = false;
108 private long timeFirstChanged; 110 private long timeFirstChanged = 0;
109 private long timeLastChanged; 111 private long timeLastChanged = 0;
112 private long m_maxPersistTime = 0;
113 private long m_minPersistTime = 0;
114 private Random m_rand;
115 private bool m_suspendUpdates;
116 private List<ScenePresence> m_linkedAvatars = new List<ScenePresence>();
117
118 public bool areUpdatesSuspended
119 {
120 get
121 {
122 return m_suspendUpdates;
123 }
124 set
125 {
126 m_suspendUpdates = value;
127 if (!value)
128 {
129 QueueForUpdateCheck();
130 }
131 }
132 }
110 133
111 public bool HasGroupChanged 134 public bool HasGroupChanged
112 { 135 {
@@ -114,9 +137,39 @@ namespace OpenSim.Region.Framework.Scenes
114 { 137 {
115 if (value) 138 if (value)
116 { 139 {
140 if (m_isBackedUp)
141 {
142 m_scene.SceneGraph.FireChangeBackup(this);
143 }
117 timeLastChanged = DateTime.Now.Ticks; 144 timeLastChanged = DateTime.Now.Ticks;
118 if (!m_hasGroupChanged) 145 if (!m_hasGroupChanged)
119 timeFirstChanged = DateTime.Now.Ticks; 146 timeFirstChanged = DateTime.Now.Ticks;
147 if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null)
148 {
149 if (m_rand == null)
150 {
151 byte[] val = new byte[16];
152 m_rootPart.UUID.ToBytes(val, 0);
153 m_rand = new Random(BitConverter.ToInt32(val, 0));
154 }
155
156 if (m_scene.GetRootAgentCount() == 0)
157 {
158 //If the region is empty, this change has been made by an automated process
159 //and thus we delay the persist time by a random amount between 1.5 and 2.5.
160
161 float factor = 1.5f + (float)(m_rand.NextDouble());
162 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor);
163 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor);
164 }
165 else
166 {
167 //If the region is not empty, we want to obey the minimum and maximum persist times
168 //but add a random factor so we stagger the object persistance a little
169 m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5
170 m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0
171 }
172 }
120 } 173 }
121 m_hasGroupChanged = value; 174 m_hasGroupChanged = value;
122 175
@@ -131,7 +184,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 184 /// 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. 185 /// an unlinked group currently has to be persisted to the database before we can perform an unlink operation.
133 /// </summary> 186 /// </summary>
134 public bool HasGroupChangedDueToDelink { get; private set; } 187 public bool HasGroupChangedDueToDelink { get; set; }
135 188
136 private bool isTimeToPersist() 189 private bool isTimeToPersist()
137 { 190 {
@@ -141,8 +194,19 @@ namespace OpenSim.Region.Framework.Scenes
141 return false; 194 return false;
142 if (m_scene.ShuttingDown) 195 if (m_scene.ShuttingDown)
143 return true; 196 return true;
197
198 if (m_minPersistTime == 0 || m_maxPersistTime == 0)
199 {
200 m_maxPersistTime = m_scene.m_persistAfter;
201 m_minPersistTime = m_scene.m_dontPersistBefore;
202 }
203
144 long currentTime = DateTime.Now.Ticks; 204 long currentTime = DateTime.Now.Ticks;
145 if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) 205
206 if (timeLastChanged == 0) timeLastChanged = currentTime;
207 if (timeFirstChanged == 0) timeFirstChanged = currentTime;
208
209 if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime)
146 return true; 210 return true;
147 return false; 211 return false;
148 } 212 }
@@ -245,10 +309,10 @@ namespace OpenSim.Region.Framework.Scenes
245 309
246 private bool m_scriptListens_atTarget; 310 private bool m_scriptListens_atTarget;
247 private bool m_scriptListens_notAtTarget; 311 private bool m_scriptListens_notAtTarget;
248
249 private bool m_scriptListens_atRotTarget; 312 private bool m_scriptListens_atRotTarget;
250 private bool m_scriptListens_notAtRotTarget; 313 private bool m_scriptListens_notAtRotTarget;
251 314
315 public bool m_dupeInProgress = false;
252 internal Dictionary<UUID, string> m_savedScriptState; 316 internal Dictionary<UUID, string> m_savedScriptState;
253 317
254 #region Properties 318 #region Properties
@@ -285,6 +349,16 @@ namespace OpenSim.Region.Framework.Scenes
285 get { return m_parts.Count; } 349 get { return m_parts.Count; }
286 } 350 }
287 351
352// protected Quaternion m_rotation = Quaternion.Identity;
353//
354// public virtual Quaternion Rotation
355// {
356// get { return m_rotation; }
357// set {
358// m_rotation = value;
359// }
360// }
361
288 public Quaternion GroupRotation 362 public Quaternion GroupRotation
289 { 363 {
290 get { return m_rootPart.RotationOffset; } 364 get { return m_rootPart.RotationOffset; }
@@ -386,14 +460,99 @@ namespace OpenSim.Region.Framework.Scenes
386 460
387 if (Scene != null) 461 if (Scene != null)
388 { 462 {
389 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 463 // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
390 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 464 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
465 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
466 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W)
467 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S))
391 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 468 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
392 { 469 {
393 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 470 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
471 uint x = 0;
472 uint y = 0;
473 string version = String.Empty;
474 Vector3 newpos = Vector3.Zero;
475 OpenSim.Services.Interfaces.GridRegion destination = null;
476
477 bool canCross = true;
478 foreach (ScenePresence av in m_linkedAvatars)
479 {
480 // We need to cross these agents. First, let's find
481 // out if any of them can't cross for some reason.
482 // We have to deny the crossing entirely if any
483 // of them are banned. Alternatively, we could
484 // unsit banned agents....
485
486
487 // We set the avatar position as being the object
488 // position to get the region to send to
489 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
490 {
491 canCross = false;
492 break;
493 }
494
495 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
496 }
497
498 if (canCross)
499 {
500 // We unparent the SP quietly so that it won't
501 // be made to stand up
502 foreach (ScenePresence av in m_linkedAvatars)
503 {
504 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
505 if (parentPart != null)
506 av.ParentUUID = parentPart.UUID;
507
508 av.ParentID = 0;
509 }
510
511 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
512
513 // Normalize
514 if (val.X >= Constants.RegionSize)
515 val.X -= Constants.RegionSize;
516 if (val.Y >= Constants.RegionSize)
517 val.Y -= Constants.RegionSize;
518 if (val.X < 0)
519 val.X += Constants.RegionSize;
520 if (val.Y < 0)
521 val.Y += Constants.RegionSize;
522
523 // If it's deleted, crossing was successful
524 if (IsDeleted)
525 {
526 foreach (ScenePresence av in m_linkedAvatars)
527 {
528 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
529
530 av.IsInTransit = true;
531
532 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
533 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
534 }
535
536 return;
537 }
538 }
539 else if (RootPart.PhysActor != null)
540 {
541 RootPart.PhysActor.CrossingFailure();
542 }
543
544 Vector3 oldp = AbsolutePosition;
545 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
546 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
547 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
394 } 548 }
395 } 549 }
396 550/* don't see the need but worse don't see where is restored to false if things stay in
551 foreach (SceneObjectPart part in m_parts.GetArray())
552 {
553 part.IgnoreUndoUpdate = true;
554 }
555 */
397 if (RootPart.GetStatusSandbox()) 556 if (RootPart.GetStatusSandbox())
398 { 557 {
399 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 558 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -407,10 +566,30 @@ namespace OpenSim.Region.Framework.Scenes
407 return; 566 return;
408 } 567 }
409 } 568 }
410
411 SceneObjectPart[] parts = m_parts.GetArray(); 569 SceneObjectPart[] parts = m_parts.GetArray();
412 for (int i = 0; i < parts.Length; i++) 570 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
413 parts[i].GroupPosition = val; 571 if (m_dupeInProgress)
572 triggerScriptEvent = false;
573 foreach (SceneObjectPart part in parts)
574 {
575 part.GroupPosition = val;
576 if (triggerScriptEvent)
577 part.TriggerScriptChangedEvent(Changed.POSITION);
578 }
579 if (!m_dupeInProgress)
580 {
581 foreach (ScenePresence av in m_linkedAvatars)
582 {
583 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
584 if (p != null && m_parts.TryGetValue(p.UUID, out p))
585 {
586 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
587 av.AbsolutePosition += offset;
588 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
589 av.SendAvatarDataToAllAgents();
590 }
591 }
592 }
414 593
415 //if (m_rootPart.PhysActor != null) 594 //if (m_rootPart.PhysActor != null)
416 //{ 595 //{
@@ -425,6 +604,29 @@ namespace OpenSim.Region.Framework.Scenes
425 } 604 }
426 } 605 }
427 606
607 public override Vector3 Velocity
608 {
609 get { return RootPart.Velocity; }
610 set { RootPart.Velocity = value; }
611 }
612
613 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
614 {
615 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
616 ScenePresence agent = icon.EndInvoke(iar);
617
618 //// If the cross was successful, this agent is a child agent
619 //if (agent.IsChildAgent)
620 // agent.Reset();
621 //else // Not successful
622 // agent.RestoreInCurrentScene();
623
624 // In any case
625 agent.IsInTransit = false;
626
627 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
628 }
629
428 public override uint LocalId 630 public override uint LocalId
429 { 631 {
430 get { return m_rootPart.LocalId; } 632 get { return m_rootPart.LocalId; }
@@ -517,6 +719,8 @@ namespace OpenSim.Region.Framework.Scenes
517 child.PhysActor.Selected = value; 719 child.PhysActor.Selected = value;
518 } 720 }
519 } 721 }
722 if (RootPart.KeyframeMotion != null)
723 RootPart.KeyframeMotion.Selected = value;
520 } 724 }
521 } 725 }
522 726
@@ -576,6 +780,7 @@ namespace OpenSim.Region.Framework.Scenes
576 /// </summary> 780 /// </summary>
577 public SceneObjectGroup() 781 public SceneObjectGroup()
578 { 782 {
783
579 } 784 }
580 785
581 /// <summary> 786 /// <summary>
@@ -592,7 +797,7 @@ namespace OpenSim.Region.Framework.Scenes
592 /// Constructor. This object is added to the scene later via AttachToScene() 797 /// Constructor. This object is added to the scene later via AttachToScene()
593 /// </summary> 798 /// </summary>
594 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 799 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
595 { 800 {
596 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 801 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
597 } 802 }
598 803
@@ -640,6 +845,9 @@ namespace OpenSim.Region.Framework.Scenes
640 /// </summary> 845 /// </summary>
641 public virtual void AttachToBackup() 846 public virtual void AttachToBackup()
642 { 847 {
848 if (IsAttachment) return;
849 m_scene.SceneGraph.FireAttachToBackup(this);
850
643 if (InSceneBackup) 851 if (InSceneBackup)
644 { 852 {
645 //m_log.DebugFormat( 853 //m_log.DebugFormat(
@@ -682,6 +890,13 @@ namespace OpenSim.Region.Framework.Scenes
682 890
683 ApplyPhysics(); 891 ApplyPhysics();
684 892
893 if (RootPart.PhysActor != null)
894 RootPart.Force = RootPart.Force;
895 if (RootPart.PhysActor != null)
896 RootPart.Torque = RootPart.Torque;
897 if (RootPart.PhysActor != null)
898 RootPart.Buoyancy = RootPart.Buoyancy;
899
685 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 900 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
686 // for the same object with very different properties. The caller must schedule the update. 901 // for the same object with very different properties. The caller must schedule the update.
687 //ScheduleGroupForFullUpdate(); 902 //ScheduleGroupForFullUpdate();
@@ -697,6 +912,10 @@ namespace OpenSim.Region.Framework.Scenes
697 EntityIntersection result = new EntityIntersection(); 912 EntityIntersection result = new EntityIntersection();
698 913
699 SceneObjectPart[] parts = m_parts.GetArray(); 914 SceneObjectPart[] parts = m_parts.GetArray();
915
916 // Find closest hit here
917 float idist = float.MaxValue;
918
700 for (int i = 0; i < parts.Length; i++) 919 for (int i = 0; i < parts.Length; i++)
701 { 920 {
702 SceneObjectPart part = parts[i]; 921 SceneObjectPart part = parts[i];
@@ -711,11 +930,6 @@ namespace OpenSim.Region.Framework.Scenes
711 930
712 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 931 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
713 932
714 // This may need to be updated to the maximum draw distance possible..
715 // We might (and probably will) be checking for prim creation from other sims
716 // when the camera crosses the border.
717 float idist = Constants.RegionSize;
718
719 if (inter.HitTF) 933 if (inter.HitTF)
720 { 934 {
721 // We need to find the closest prim to return to the testcaller along the ray 935 // We need to find the closest prim to return to the testcaller along the ray
@@ -726,10 +940,11 @@ namespace OpenSim.Region.Framework.Scenes
726 result.obj = part; 940 result.obj = part;
727 result.normal = inter.normal; 941 result.normal = inter.normal;
728 result.distance = inter.distance; 942 result.distance = inter.distance;
943
944 idist = inter.distance;
729 } 945 }
730 } 946 }
731 } 947 }
732
733 return result; 948 return result;
734 } 949 }
735 950
@@ -741,25 +956,27 @@ namespace OpenSim.Region.Framework.Scenes
741 /// <returns></returns> 956 /// <returns></returns>
742 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 957 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
743 { 958 {
744 maxX = -256f; 959 maxX = float.MinValue;
745 maxY = -256f; 960 maxY = float.MinValue;
746 maxZ = -256f; 961 maxZ = float.MinValue;
747 minX = 256f; 962 minX = float.MaxValue;
748 minY = 256f; 963 minY = float.MaxValue;
749 minZ = 8192f; 964 minZ = float.MaxValue;
750 965
751 SceneObjectPart[] parts = m_parts.GetArray(); 966 SceneObjectPart[] parts = m_parts.GetArray();
752 for (int i = 0; i < parts.Length; i++) 967 foreach (SceneObjectPart part in parts)
753 { 968 {
754 SceneObjectPart part = parts[i];
755
756 Vector3 worldPos = part.GetWorldPosition(); 969 Vector3 worldPos = part.GetWorldPosition();
757 Vector3 offset = worldPos - AbsolutePosition; 970 Vector3 offset = worldPos - AbsolutePosition;
758 Quaternion worldRot; 971 Quaternion worldRot;
759 if (part.ParentID == 0) 972 if (part.ParentID == 0)
973 {
760 worldRot = part.RotationOffset; 974 worldRot = part.RotationOffset;
975 }
761 else 976 else
977 {
762 worldRot = part.GetWorldRotation(); 978 worldRot = part.GetWorldRotation();
979 }
763 980
764 Vector3 frontTopLeft; 981 Vector3 frontTopLeft;
765 Vector3 frontTopRight; 982 Vector3 frontTopRight;
@@ -771,6 +988,8 @@ namespace OpenSim.Region.Framework.Scenes
771 Vector3 backBottomLeft; 988 Vector3 backBottomLeft;
772 Vector3 backBottomRight; 989 Vector3 backBottomRight;
773 990
991 // Vector3[] corners = new Vector3[8];
992
774 Vector3 orig = Vector3.Zero; 993 Vector3 orig = Vector3.Zero;
775 994
776 frontTopLeft.X = orig.X - (part.Scale.X / 2); 995 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -805,6 +1024,38 @@ namespace OpenSim.Region.Framework.Scenes
805 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1024 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
806 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1025 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
807 1026
1027
1028
1029 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1030 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1031 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1032 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1033 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1034 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1035 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1036 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1037
1038 //for (int i = 0; i < 8; i++)
1039 //{
1040 // corners[i] = corners[i] * worldRot;
1041 // corners[i] += offset;
1042
1043 // if (corners[i].X > maxX)
1044 // maxX = corners[i].X;
1045 // if (corners[i].X < minX)
1046 // minX = corners[i].X;
1047
1048 // if (corners[i].Y > maxY)
1049 // maxY = corners[i].Y;
1050 // if (corners[i].Y < minY)
1051 // minY = corners[i].Y;
1052
1053 // if (corners[i].Z > maxZ)
1054 // maxZ = corners[i].Y;
1055 // if (corners[i].Z < minZ)
1056 // minZ = corners[i].Z;
1057 //}
1058
808 frontTopLeft = frontTopLeft * worldRot; 1059 frontTopLeft = frontTopLeft * worldRot;
809 frontTopRight = frontTopRight * worldRot; 1060 frontTopRight = frontTopRight * worldRot;
810 frontBottomLeft = frontBottomLeft * worldRot; 1061 frontBottomLeft = frontBottomLeft * worldRot;
@@ -826,6 +1077,15 @@ namespace OpenSim.Region.Framework.Scenes
826 backTopLeft += offset; 1077 backTopLeft += offset;
827 backTopRight += offset; 1078 backTopRight += offset;
828 1079
1080 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1081 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1082 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1083 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1084 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1085 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1086 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1087 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1088
829 if (frontTopRight.X > maxX) 1089 if (frontTopRight.X > maxX)
830 maxX = frontTopRight.X; 1090 maxX = frontTopRight.X;
831 if (frontTopLeft.X > maxX) 1091 if (frontTopLeft.X > maxX)
@@ -969,17 +1229,118 @@ namespace OpenSim.Region.Framework.Scenes
969 1229
970 #endregion 1230 #endregion
971 1231
1232 public void GetResourcesCosts(SceneObjectPart apart,
1233 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1234 {
1235 // this information may need to be cached
1236
1237 float cost;
1238 float tmpcost;
1239
1240 bool ComplexCost = false;
1241
1242 SceneObjectPart p;
1243 SceneObjectPart[] parts;
1244
1245 lock (m_parts)
1246 {
1247 parts = m_parts.GetArray();
1248 }
1249
1250 int nparts = parts.Length;
1251
1252
1253 for (int i = 0; i < nparts; i++)
1254 {
1255 p = parts[i];
1256
1257 if (p.UsesComplexCost)
1258 {
1259 ComplexCost = true;
1260 break;
1261 }
1262 }
1263
1264 if (ComplexCost)
1265 {
1266 linksetResCost = 0;
1267 linksetPhysCost = 0;
1268 partCost = 0;
1269 partPhysCost = 0;
1270
1271 for (int i = 0; i < nparts; i++)
1272 {
1273 p = parts[i];
1274
1275 cost = p.StreamingCost;
1276 tmpcost = p.SimulationCost;
1277 if (tmpcost > cost)
1278 cost = tmpcost;
1279 tmpcost = p.PhysicsCost;
1280 if (tmpcost > cost)
1281 cost = tmpcost;
1282
1283 linksetPhysCost += tmpcost;
1284 linksetResCost += cost;
1285
1286 if (p == apart)
1287 {
1288 partCost = cost;
1289 partPhysCost = tmpcost;
1290 }
1291 }
1292 }
1293 else
1294 {
1295 partPhysCost = 1.0f;
1296 partCost = 1.0f;
1297 linksetResCost = (float)nparts;
1298 linksetPhysCost = linksetResCost;
1299 }
1300 }
1301
1302 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1303 {
1304 SceneObjectPart p;
1305 SceneObjectPart[] parts;
1306
1307 lock (m_parts)
1308 {
1309 parts = m_parts.GetArray();
1310 }
1311
1312 int nparts = parts.Length;
1313
1314 PhysCost = 0;
1315 StreamCost = 0;
1316 SimulCost = 0;
1317
1318 for (int i = 0; i < nparts; i++)
1319 {
1320 p = parts[i];
1321
1322 StreamCost += p.StreamingCost;
1323 SimulCost += p.SimulationCost;
1324 PhysCost += p.PhysicsCost;
1325 }
1326 }
1327
972 public void SaveScriptedState(XmlTextWriter writer) 1328 public void SaveScriptedState(XmlTextWriter writer)
973 { 1329 {
1330 SaveScriptedState(writer, false);
1331 }
1332
1333 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1334 {
974 XmlDocument doc = new XmlDocument(); 1335 XmlDocument doc = new XmlDocument();
975 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1336 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
976 1337
977 SceneObjectPart[] parts = m_parts.GetArray(); 1338 SceneObjectPart[] parts = m_parts.GetArray();
978 for (int i = 0; i < parts.Length; i++) 1339 for (int i = 0; i < parts.Length; i++)
979 { 1340 {
980 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1341 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
981 foreach (KeyValuePair<UUID, string> kvp in pstates) 1342 foreach (KeyValuePair<UUID, string> kvp in pstates)
982 states.Add(kvp.Key, kvp.Value); 1343 states[kvp.Key] = kvp.Value;
983 } 1344 }
984 1345
985 if (states.Count > 0) 1346 if (states.Count > 0)
@@ -999,6 +1360,169 @@ namespace OpenSim.Region.Framework.Scenes
999 } 1360 }
1000 1361
1001 /// <summary> 1362 /// <summary>
1363 /// Add the avatar to this linkset (avatar is sat).
1364 /// </summary>
1365 /// <param name="agentID"></param>
1366 public void AddAvatar(UUID agentID)
1367 {
1368 ScenePresence presence;
1369 if (m_scene.TryGetScenePresence(agentID, out presence))
1370 {
1371 if (!m_linkedAvatars.Contains(presence))
1372 {
1373 m_linkedAvatars.Add(presence);
1374 }
1375 }
1376 }
1377
1378 /// <summary>
1379 /// Delete the avatar from this linkset (avatar is unsat).
1380 /// </summary>
1381 /// <param name="agentID"></param>
1382 public void DeleteAvatar(UUID agentID)
1383 {
1384 ScenePresence presence;
1385 if (m_scene.TryGetScenePresence(agentID, out presence))
1386 {
1387 if (m_linkedAvatars.Contains(presence))
1388 {
1389 m_linkedAvatars.Remove(presence);
1390 }
1391 }
1392 }
1393
1394 /// <summary>
1395 /// Returns the list of linked presences (avatars sat on this group)
1396 /// </summary>
1397 /// <param name="agentID"></param>
1398 public List<ScenePresence> GetLinkedAvatars()
1399 {
1400 return m_linkedAvatars;
1401 }
1402
1403 /// <summary>
1404 /// Attach this scene object to the given avatar.
1405 /// </summary>
1406 /// <param name="agentID"></param>
1407 /// <param name="attachmentpoint"></param>
1408 /// <param name="AttachOffset"></param>
1409 private void AttachToAgent(
1410 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1411 {
1412 if (avatar != null)
1413 {
1414 // don't attach attachments to child agents
1415 if (avatar.IsChildAgent) return;
1416
1417 // Remove from database and parcel prim count
1418 m_scene.DeleteFromStorage(so.UUID);
1419 m_scene.EventManager.TriggerParcelPrimCountTainted();
1420
1421 so.AttachedAvatar = avatar.UUID;
1422
1423 if (so.RootPart.PhysActor != null)
1424 {
1425 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1426 so.RootPart.PhysActor = null;
1427 }
1428
1429 so.AbsolutePosition = attachOffset;
1430 so.RootPart.AttachedPos = attachOffset;
1431 so.IsAttachment = true;
1432 so.RootPart.SetParentLocalId(avatar.LocalId);
1433 so.AttachmentPoint = attachmentpoint;
1434
1435 avatar.AddAttachment(this);
1436
1437 if (!silent)
1438 {
1439 // Killing it here will cause the client to deselect it
1440 // It then reappears on the avatar, deselected
1441 // through the full update below
1442 //
1443 if (IsSelected)
1444 {
1445 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1446 }
1447
1448 IsSelected = false; // fudge....
1449 ScheduleGroupForFullUpdate();
1450 }
1451 }
1452 else
1453 {
1454 m_log.WarnFormat(
1455 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1456 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1457 }
1458 }
1459
1460 public byte GetAttachmentPoint()
1461 {
1462 return m_rootPart.Shape.State;
1463 }
1464
1465 public void DetachToGround()
1466 {
1467 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1468 if (avatar == null)
1469 return;
1470
1471 avatar.RemoveAttachment(this);
1472
1473 Vector3 detachedpos = new Vector3(127f,127f,127f);
1474 if (avatar == null)
1475 return;
1476
1477 detachedpos = avatar.AbsolutePosition;
1478 RootPart.FromItemID = UUID.Zero;
1479
1480 AbsolutePosition = detachedpos;
1481 AttachedAvatar = UUID.Zero;
1482
1483 //SceneObjectPart[] parts = m_parts.GetArray();
1484 //for (int i = 0; i < parts.Length; i++)
1485 // parts[i].AttachedAvatar = UUID.Zero;
1486
1487 m_rootPart.SetParentLocalId(0);
1488 AttachmentPoint = (byte)0;
1489 // must check if buildind should be true or false here
1490 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1491 HasGroupChanged = true;
1492 RootPart.Rezzed = DateTime.Now;
1493 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1494 AttachToBackup();
1495 m_scene.EventManager.TriggerParcelPrimCountTainted();
1496 m_rootPart.ScheduleFullUpdate();
1497 m_rootPart.ClearUndoState();
1498 }
1499
1500 public void DetachToInventoryPrep()
1501 {
1502 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1503 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1504 if (avatar != null)
1505 {
1506 //detachedpos = avatar.AbsolutePosition;
1507 avatar.RemoveAttachment(this);
1508 }
1509
1510 AttachedAvatar = UUID.Zero;
1511
1512 /*SceneObjectPart[] parts = m_parts.GetArray();
1513 for (int i = 0; i < parts.Length; i++)
1514 parts[i].AttachedAvatar = UUID.Zero;*/
1515
1516 m_rootPart.SetParentLocalId(0);
1517 //m_rootPart.SetAttachmentPoint((byte)0);
1518 IsAttachment = false;
1519 AbsolutePosition = m_rootPart.AttachedPos;
1520 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1521 //AttachToBackup();
1522 //m_rootPart.ScheduleFullUpdate();
1523 }
1524
1525 /// <summary>
1002 /// 1526 ///
1003 /// </summary> 1527 /// </summary>
1004 /// <param name="part"></param> 1528 /// <param name="part"></param>
@@ -1048,7 +1572,10 @@ namespace OpenSim.Region.Framework.Scenes
1048 public void AddPart(SceneObjectPart part) 1572 public void AddPart(SceneObjectPart part)
1049 { 1573 {
1050 part.SetParent(this); 1574 part.SetParent(this);
1051 part.LinkNum = m_parts.Add(part.UUID, part); 1575 m_parts.Add(part.UUID, part);
1576
1577 part.LinkNum = m_parts.Count;
1578
1052 if (part.LinkNum == 2) 1579 if (part.LinkNum == 2)
1053 RootPart.LinkNum = 1; 1580 RootPart.LinkNum = 1;
1054 } 1581 }
@@ -1136,7 +1663,7 @@ namespace OpenSim.Region.Framework.Scenes
1136// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1663// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1137// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1664// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1138 1665
1139 part.StoreUndoState(); 1666// part.StoreUndoState();
1140 part.OnGrab(offsetPos, remoteClient); 1667 part.OnGrab(offsetPos, remoteClient);
1141 } 1668 }
1142 1669
@@ -1156,6 +1683,11 @@ namespace OpenSim.Region.Framework.Scenes
1156 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1683 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1157 public void DeleteGroupFromScene(bool silent) 1684 public void DeleteGroupFromScene(bool silent)
1158 { 1685 {
1686 // We need to keep track of this state in case this group is still queued for backup.
1687 IsDeleted = true;
1688
1689 DetachFromBackup();
1690
1159 SceneObjectPart[] parts = m_parts.GetArray(); 1691 SceneObjectPart[] parts = m_parts.GetArray();
1160 for (int i = 0; i < parts.Length; i++) 1692 for (int i = 0; i < parts.Length; i++)
1161 { 1693 {
@@ -1178,6 +1710,8 @@ namespace OpenSim.Region.Framework.Scenes
1178 } 1710 }
1179 }); 1711 });
1180 } 1712 }
1713
1714
1181 } 1715 }
1182 1716
1183 public void AddScriptLPS(int count) 1717 public void AddScriptLPS(int count)
@@ -1247,28 +1781,43 @@ namespace OpenSim.Region.Framework.Scenes
1247 /// </summary> 1781 /// </summary>
1248 public void ApplyPhysics() 1782 public void ApplyPhysics()
1249 { 1783 {
1250 // Apply physics to the root prim
1251 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1252
1253 // Apply physics to child prims
1254 SceneObjectPart[] parts = m_parts.GetArray(); 1784 SceneObjectPart[] parts = m_parts.GetArray();
1255 if (parts.Length > 1) 1785 if (parts.Length > 1)
1256 { 1786 {
1787 ResetChildPrimPhysicsPositions();
1788
1789 // Apply physics to the root prim
1790 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
1791
1792
1257 for (int i = 0; i < parts.Length; i++) 1793 for (int i = 0; i < parts.Length; i++)
1258 { 1794 {
1259 SceneObjectPart part = parts[i]; 1795 SceneObjectPart part = parts[i];
1260 if (part.LocalId != m_rootPart.LocalId) 1796 if (part.LocalId != m_rootPart.LocalId)
1261 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 1797 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1262 } 1798 }
1263
1264 // Hack to get the physics scene geometries in the right spot 1799 // Hack to get the physics scene geometries in the right spot
1265 ResetChildPrimPhysicsPositions(); 1800// ResetChildPrimPhysicsPositions();
1801 if (m_rootPart.PhysActor != null)
1802 {
1803 m_rootPart.PhysActor.Building = false;
1804 }
1805 }
1806 else
1807 {
1808 // Apply physics to the root prim
1809 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1266 } 1810 }
1267 } 1811 }
1268 1812
1269 public void SetOwnerId(UUID userId) 1813 public void SetOwnerId(UUID userId)
1270 { 1814 {
1271 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1815 ForEachPart(delegate(SceneObjectPart part)
1816 {
1817
1818 part.OwnerID = userId;
1819
1820 });
1272 } 1821 }
1273 1822
1274 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1823 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1300,11 +1849,17 @@ namespace OpenSim.Region.Framework.Scenes
1300 return; 1849 return;
1301 } 1850 }
1302 1851
1852 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1853 return;
1854
1303 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1855 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1304 // any exception propogate upwards. 1856 // any exception propogate upwards.
1305 try 1857 try
1306 { 1858 {
1307 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1859 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1860 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1861 m_scene.LoadingPrims) // Land may not be valid yet
1862
1308 { 1863 {
1309 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1864 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1310 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1865 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1331,6 +1886,7 @@ namespace OpenSim.Region.Framework.Scenes
1331 } 1886 }
1332 } 1887 }
1333 } 1888 }
1889
1334 } 1890 }
1335 1891
1336 if (m_scene.UseBackup && HasGroupChanged) 1892 if (m_scene.UseBackup && HasGroupChanged)
@@ -1338,6 +1894,20 @@ namespace OpenSim.Region.Framework.Scenes
1338 // don't backup while it's selected or you're asking for changes mid stream. 1894 // don't backup while it's selected or you're asking for changes mid stream.
1339 if (isTimeToPersist() || forcedBackup) 1895 if (isTimeToPersist() || forcedBackup)
1340 { 1896 {
1897 if (m_rootPart.PhysActor != null &&
1898 (!m_rootPart.PhysActor.IsPhysical))
1899 {
1900 // Possible ghost prim
1901 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1902 {
1903 foreach (SceneObjectPart part in m_parts.GetArray())
1904 {
1905 // Re-set physics actor positions and
1906 // orientations
1907 part.GroupPosition = m_rootPart.GroupPosition;
1908 }
1909 }
1910 }
1341// m_log.DebugFormat( 1911// m_log.DebugFormat(
1342// "[SCENE]: Storing {0}, {1} in {2}", 1912// "[SCENE]: Storing {0}, {1} in {2}",
1343// Name, UUID, m_scene.RegionInfo.RegionName); 1913// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1355,6 +1925,11 @@ namespace OpenSim.Region.Framework.Scenes
1355 1925
1356 backup_group.ForEachPart(delegate(SceneObjectPart part) 1926 backup_group.ForEachPart(delegate(SceneObjectPart part)
1357 { 1927 {
1928 if (part.KeyframeMotion != null)
1929 {
1930 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
1931 part.KeyframeMotion.UpdateSceneObject(this);
1932 }
1358 part.Inventory.ProcessInventoryBackup(datastore); 1933 part.Inventory.ProcessInventoryBackup(datastore);
1359 }); 1934 });
1360 1935
@@ -1407,6 +1982,7 @@ namespace OpenSim.Region.Framework.Scenes
1407 /// <returns></returns> 1982 /// <returns></returns>
1408 public SceneObjectGroup Copy(bool userExposed) 1983 public SceneObjectGroup Copy(bool userExposed)
1409 { 1984 {
1985 m_dupeInProgress = true;
1410 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 1986 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1411 dupe.m_isBackedUp = false; 1987 dupe.m_isBackedUp = false;
1412 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 1988 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
@@ -1421,7 +1997,7 @@ namespace OpenSim.Region.Framework.Scenes
1421 // This is only necessary when userExposed is false! 1997 // This is only necessary when userExposed is false!
1422 1998
1423 bool previousAttachmentStatus = dupe.IsAttachment; 1999 bool previousAttachmentStatus = dupe.IsAttachment;
1424 2000
1425 if (!userExposed) 2001 if (!userExposed)
1426 dupe.IsAttachment = true; 2002 dupe.IsAttachment = true;
1427 2003
@@ -1439,11 +2015,11 @@ namespace OpenSim.Region.Framework.Scenes
1439 dupe.m_rootPart.TrimPermissions(); 2015 dupe.m_rootPart.TrimPermissions();
1440 2016
1441 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2017 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1442 2018
1443 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2019 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1444 { 2020 {
1445 return p1.LinkNum.CompareTo(p2.LinkNum); 2021 return p1.LinkNum.CompareTo(p2.LinkNum);
1446 } 2022 }
1447 ); 2023 );
1448 2024
1449 foreach (SceneObjectPart part in partList) 2025 foreach (SceneObjectPart part in partList)
@@ -1453,40 +2029,53 @@ namespace OpenSim.Region.Framework.Scenes
1453 { 2029 {
1454 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2030 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1455 newPart.LinkNum = part.LinkNum; 2031 newPart.LinkNum = part.LinkNum;
1456 } 2032 if (userExposed)
2033 newPart.ParentID = dupe.m_rootPart.LocalId;
2034 }
1457 else 2035 else
1458 { 2036 {
1459 newPart = dupe.m_rootPart; 2037 newPart = dupe.m_rootPart;
1460 } 2038 }
2039/*
2040 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2041 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1461 2042
1462 // Need to duplicate the physics actor as well 2043 // Need to duplicate the physics actor as well
1463 if (part.PhysActor != null && userExposed) 2044 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1464 { 2045 {
1465 PrimitiveBaseShape pbs = newPart.Shape; 2046 PrimitiveBaseShape pbs = newPart.Shape;
1466
1467 newPart.PhysActor 2047 newPart.PhysActor
1468 = m_scene.PhysicsScene.AddPrimShape( 2048 = m_scene.PhysicsScene.AddPrimShape(
1469 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2049 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1470 pbs, 2050 pbs,
1471 newPart.AbsolutePosition, 2051 newPart.AbsolutePosition,
1472 newPart.Scale, 2052 newPart.Scale,
1473 newPart.RotationOffset, 2053 newPart.GetWorldRotation(),
1474 part.PhysActor.IsPhysical, 2054 isphys,
2055 isphan,
1475 newPart.LocalId); 2056 newPart.LocalId);
1476 2057
1477 newPart.DoPhysicsPropertyUpdate(part.PhysActor.IsPhysical, true); 2058 newPart.DoPhysicsPropertyUpdate(isphys, true);
1478 } 2059 */
2060 if (userExposed)
2061 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2062// }
1479 } 2063 }
1480 2064
1481 if (userExposed) 2065 if (userExposed)
1482 { 2066 {
1483 dupe.UpdateParentIDs(); 2067// done above dupe.UpdateParentIDs();
2068
2069 if (dupe.m_rootPart.PhysActor != null)
2070 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2071
1484 dupe.HasGroupChanged = true; 2072 dupe.HasGroupChanged = true;
1485 dupe.AttachToBackup(); 2073 dupe.AttachToBackup();
1486 2074
1487 ScheduleGroupForFullUpdate(); 2075 ScheduleGroupForFullUpdate();
1488 } 2076 }
1489 2077
2078 m_dupeInProgress = false;
1490 return dupe; 2079 return dupe;
1491 } 2080 }
1492 2081
@@ -1498,11 +2087,24 @@ namespace OpenSim.Region.Framework.Scenes
1498 /// <param name="cGroupID"></param> 2087 /// <param name="cGroupID"></param>
1499 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2088 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1500 { 2089 {
1501 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2090 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
2091 // give newpart a new local ID lettng old part keep same
2092 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2093 newpart.LocalId = m_scene.AllocateLocalId();
2094
2095 SetRootPart(newpart);
2096 if (userExposed)
2097 RootPart.Velocity = Vector3.Zero; // In case source is moving
1502 } 2098 }
1503 2099
1504 public void ScriptSetPhysicsStatus(bool usePhysics) 2100 public void ScriptSetPhysicsStatus(bool usePhysics)
1505 { 2101 {
2102 if (usePhysics)
2103 {
2104 if (RootPart.KeyframeMotion != null)
2105 RootPart.KeyframeMotion.Stop();
2106 RootPart.KeyframeMotion = null;
2107 }
1506 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2108 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1507 } 2109 }
1508 2110
@@ -1566,32 +2168,12 @@ namespace OpenSim.Region.Framework.Scenes
1566 } 2168 }
1567 } 2169 }
1568 2170
1569 public void setAngularImpulse(Vector3 impulse)
1570 {
1571 if (RootPart.PhysActor != null)
1572 {
1573 if (!IsAttachment)
1574 {
1575 RootPart.PhysActor.Torque = impulse;
1576 m_scene.PhysicsScene.AddPhysicsActorTaint(RootPart.PhysActor);
1577 }
1578 }
1579 }
1580
1581 public Vector3 GetTorque() 2171 public Vector3 GetTorque()
1582 { 2172 {
1583 if (RootPart.PhysActor != null) 2173 return RootPart.Torque;
1584 {
1585 if (!IsAttachment)
1586 {
1587 Vector3 torque = RootPart.PhysActor.Torque;
1588 return torque;
1589 }
1590 }
1591
1592 return Vector3.Zero;
1593 } 2174 }
1594 2175
2176 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1595 public void moveToTarget(Vector3 target, float tau) 2177 public void moveToTarget(Vector3 target, float tau)
1596 { 2178 {
1597 if (IsAttachment) 2179 if (IsAttachment)
@@ -1619,6 +2201,46 @@ namespace OpenSim.Region.Framework.Scenes
1619 RootPart.PhysActor.PIDActive = false; 2201 RootPart.PhysActor.PIDActive = false;
1620 } 2202 }
1621 2203
2204 public void rotLookAt(Quaternion target, float strength, float damping)
2205 {
2206 SceneObjectPart rootpart = m_rootPart;
2207 if (rootpart != null)
2208 {
2209 if (IsAttachment)
2210 {
2211 /*
2212 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2213 if (avatar != null)
2214 {
2215 Rotate the Av?
2216 } */
2217 }
2218 else
2219 {
2220 if (rootpart.PhysActor != null)
2221 { // APID must be implemented in your physics system for this to function.
2222 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2223 rootpart.PhysActor.APIDStrength = strength;
2224 rootpart.PhysActor.APIDDamping = damping;
2225 rootpart.PhysActor.APIDActive = true;
2226 }
2227 }
2228 }
2229 }
2230
2231 public void stopLookAt()
2232 {
2233 SceneObjectPart rootpart = m_rootPart;
2234 if (rootpart != null)
2235 {
2236 if (rootpart.PhysActor != null)
2237 { // APID must be implemented in your physics system for this to function.
2238 rootpart.PhysActor.APIDActive = false;
2239 }
2240 }
2241
2242 }
2243
1622 /// <summary> 2244 /// <summary>
1623 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2245 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1624 /// </summary> 2246 /// </summary>
@@ -1673,7 +2295,12 @@ namespace OpenSim.Region.Framework.Scenes
1673 /// <param name="cGroupID"></param> 2295 /// <param name="cGroupID"></param>
1674 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2296 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1675 { 2297 {
1676 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2298 // give new ID to the new part, letting old keep original
2299 // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2300 SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2301 newPart.LocalId = m_scene.AllocateLocalId();
2302 newPart.SetParent(this);
2303
1677 AddPart(newPart); 2304 AddPart(newPart);
1678 2305
1679 SetPartAsNonRoot(newPart); 2306 SetPartAsNonRoot(newPart);
@@ -1802,11 +2429,11 @@ namespace OpenSim.Region.Framework.Scenes
1802 /// Immediately send a full update for this scene object. 2429 /// Immediately send a full update for this scene object.
1803 /// </summary> 2430 /// </summary>
1804 public void SendGroupFullUpdate() 2431 public void SendGroupFullUpdate()
1805 { 2432 {
1806 if (IsDeleted) 2433 if (IsDeleted)
1807 return; 2434 return;
1808 2435
1809// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2436// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1810 2437
1811 RootPart.SendFullUpdateToAllClients(); 2438 RootPart.SendFullUpdateToAllClients();
1812 2439
@@ -1950,6 +2577,11 @@ namespace OpenSim.Region.Framework.Scenes
1950 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2577 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1951 public void LinkToGroup(SceneObjectGroup objectGroup) 2578 public void LinkToGroup(SceneObjectGroup objectGroup)
1952 { 2579 {
2580 LinkToGroup(objectGroup, false);
2581 }
2582
2583 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2584 {
1953// m_log.DebugFormat( 2585// m_log.DebugFormat(
1954// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2586// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1955// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2587// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
@@ -1960,6 +2592,15 @@ namespace OpenSim.Region.Framework.Scenes
1960 2592
1961 SceneObjectPart linkPart = objectGroup.m_rootPart; 2593 SceneObjectPart linkPart = objectGroup.m_rootPart;
1962 2594
2595 if (m_rootPart.PhysActor != null)
2596 m_rootPart.PhysActor.Building = true;
2597 if (linkPart.PhysActor != null)
2598 linkPart.PhysActor.Building = true;
2599
2600 // physics flags from group to be applied to linked parts
2601 bool grpusephys = UsesPhysics;
2602 bool grptemporary = IsTemporary;
2603
1963 Vector3 oldGroupPosition = linkPart.GroupPosition; 2604 Vector3 oldGroupPosition = linkPart.GroupPosition;
1964 Quaternion oldRootRotation = linkPart.RotationOffset; 2605 Quaternion oldRootRotation = linkPart.RotationOffset;
1965 2606
@@ -1983,13 +2624,34 @@ namespace OpenSim.Region.Framework.Scenes
1983 2624
1984 lock (m_parts.SyncRoot) 2625 lock (m_parts.SyncRoot)
1985 { 2626 {
1986 int linkNum = PrimCount + 1; 2627 int linkNum;
2628 if (insert)
2629 {
2630 linkNum = 2;
2631 foreach (SceneObjectPart part in Parts)
2632 {
2633 if (part.LinkNum > 1)
2634 part.LinkNum++;
2635 }
2636 }
2637 else
2638 {
2639 linkNum = PrimCount + 1;
2640 }
1987 2641
1988 m_parts.Add(linkPart.UUID, linkPart); 2642 m_parts.Add(linkPart.UUID, linkPart);
1989 2643
1990 linkPart.SetParent(this); 2644 linkPart.SetParent(this);
1991 linkPart.CreateSelected = true; 2645 linkPart.CreateSelected = true;
1992 2646
2647 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2648 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2649 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2650 {
2651 linkPart.PhysActor.link(m_rootPart.PhysActor);
2652 this.Scene.PhysicsScene.AddPhysicsActorTaint(linkPart.PhysActor);
2653 }
2654
1993 linkPart.LinkNum = linkNum++; 2655 linkPart.LinkNum = linkNum++;
1994 2656
1995 SceneObjectPart[] ogParts = objectGroup.Parts; 2657 SceneObjectPart[] ogParts = objectGroup.Parts;
@@ -2002,7 +2664,16 @@ namespace OpenSim.Region.Framework.Scenes
2002 { 2664 {
2003 SceneObjectPart part = ogParts[i]; 2665 SceneObjectPart part = ogParts[i];
2004 if (part.UUID != objectGroup.m_rootPart.UUID) 2666 if (part.UUID != objectGroup.m_rootPart.UUID)
2667 {
2005 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2668 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2669 // let physics know
2670 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2671 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2672 {
2673 part.PhysActor.link(m_rootPart.PhysActor);
2674 this.Scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2675 }
2676 }
2006 part.ClearUndoState(); 2677 part.ClearUndoState();
2007 } 2678 }
2008 } 2679 }
@@ -2011,7 +2682,7 @@ namespace OpenSim.Region.Framework.Scenes
2011 objectGroup.IsDeleted = true; 2682 objectGroup.IsDeleted = true;
2012 2683
2013 objectGroup.m_parts.Clear(); 2684 objectGroup.m_parts.Clear();
2014 2685
2015 // Can't do this yet since backup still makes use of the root part without any synchronization 2686 // Can't do this yet since backup still makes use of the root part without any synchronization
2016// objectGroup.m_rootPart = null; 2687// objectGroup.m_rootPart = null;
2017 2688
@@ -2022,6 +2693,9 @@ namespace OpenSim.Region.Framework.Scenes
2022 // unmoved prims! 2693 // unmoved prims!
2023 ResetChildPrimPhysicsPositions(); 2694 ResetChildPrimPhysicsPositions();
2024 2695
2696 if (m_rootPart.PhysActor != null)
2697 m_rootPart.PhysActor.Building = false;
2698
2025 //HasGroupChanged = true; 2699 //HasGroupChanged = true;
2026 //ScheduleGroupForFullUpdate(); 2700 //ScheduleGroupForFullUpdate();
2027 } 2701 }
@@ -2074,7 +2748,10 @@ namespace OpenSim.Region.Framework.Scenes
2074// m_log.DebugFormat( 2748// m_log.DebugFormat(
2075// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 2749// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2076// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 2750// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2077 2751
2752 if (m_rootPart.PhysActor != null)
2753 m_rootPart.PhysActor.Building = true;
2754
2078 linkPart.ClearUndoState(); 2755 linkPart.ClearUndoState();
2079 2756
2080 Quaternion worldRot = linkPart.GetWorldRotation(); 2757 Quaternion worldRot = linkPart.GetWorldRotation();
@@ -2134,6 +2811,14 @@ namespace OpenSim.Region.Framework.Scenes
2134 2811
2135 // When we delete a group, we currently have to force persist to the database if the object id has changed 2812 // When we delete a group, we currently have to force persist to the database if the object id has changed
2136 // (since delete works by deleting all rows which have a given object id) 2813 // (since delete works by deleting all rows which have a given object id)
2814
2815 // this is as it seems to be in sl now
2816 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2817 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2818
2819 if (m_rootPart.PhysActor != null)
2820 m_rootPart.PhysActor.Building = false;
2821
2137 objectGroup.HasGroupChangedDueToDelink = true; 2822 objectGroup.HasGroupChangedDueToDelink = true;
2138 2823
2139 return objectGroup; 2824 return objectGroup;
@@ -2145,6 +2830,7 @@ namespace OpenSim.Region.Framework.Scenes
2145 /// <param name="objectGroup"></param> 2830 /// <param name="objectGroup"></param>
2146 public virtual void DetachFromBackup() 2831 public virtual void DetachFromBackup()
2147 { 2832 {
2833 m_scene.SceneGraph.FireDetachFromBackup(this);
2148 if (m_isBackedUp && Scene != null) 2834 if (m_isBackedUp && Scene != null)
2149 m_scene.EventManager.OnBackup -= ProcessBackup; 2835 m_scene.EventManager.OnBackup -= ProcessBackup;
2150 2836
@@ -2163,7 +2849,8 @@ namespace OpenSim.Region.Framework.Scenes
2163 2849
2164 axPos *= parentRot; 2850 axPos *= parentRot;
2165 part.OffsetPosition = axPos; 2851 part.OffsetPosition = axPos;
2166 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2852 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2853 part.GroupPosition = newPos;
2167 part.OffsetPosition = Vector3.Zero; 2854 part.OffsetPosition = Vector3.Zero;
2168 part.RotationOffset = worldRot; 2855 part.RotationOffset = worldRot;
2169 2856
@@ -2174,7 +2861,7 @@ namespace OpenSim.Region.Framework.Scenes
2174 2861
2175 part.LinkNum = linkNum; 2862 part.LinkNum = linkNum;
2176 2863
2177 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2864 part.OffsetPosition = newPos - AbsolutePosition;
2178 2865
2179 Quaternion rootRotation = m_rootPart.RotationOffset; 2866 Quaternion rootRotation = m_rootPart.RotationOffset;
2180 2867
@@ -2184,7 +2871,7 @@ namespace OpenSim.Region.Framework.Scenes
2184 2871
2185 parentRot = m_rootPart.RotationOffset; 2872 parentRot = m_rootPart.RotationOffset;
2186 oldRot = part.RotationOffset; 2873 oldRot = part.RotationOffset;
2187 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2874 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2188 part.RotationOffset = newRot; 2875 part.RotationOffset = newRot;
2189 } 2876 }
2190 2877
@@ -2431,8 +3118,31 @@ namespace OpenSim.Region.Framework.Scenes
2431 } 3118 }
2432 } 3119 }
2433 3120
3121/*
3122 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2434 for (int i = 0; i < parts.Length; i++) 3123 for (int i = 0; i < parts.Length; i++)
2435 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3124 {
3125 if (parts[i] != RootPart)
3126 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
3127 }
3128*/
3129 if (parts.Length > 1)
3130 {
3131 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3132
3133 for (int i = 0; i < parts.Length; i++)
3134 {
3135
3136 if (parts[i].UUID != m_rootPart.UUID)
3137 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3138 }
3139
3140 if (m_rootPart.PhysActor != null)
3141 m_rootPart.PhysActor.Building = false;
3142 }
3143 else
3144 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
3145
2436 } 3146 }
2437 } 3147 }
2438 3148
@@ -2445,6 +3155,17 @@ namespace OpenSim.Region.Framework.Scenes
2445 } 3155 }
2446 } 3156 }
2447 3157
3158
3159
3160 /// <summary>
3161 /// Gets the number of parts
3162 /// </summary>
3163 /// <returns></returns>
3164 public int GetPartCount()
3165 {
3166 return Parts.Count();
3167 }
3168
2448 /// <summary> 3169 /// <summary>
2449 /// Update the texture entry for this part 3170 /// Update the texture entry for this part
2450 /// </summary> 3171 /// </summary>
@@ -2504,11 +3225,6 @@ namespace OpenSim.Region.Framework.Scenes
2504 /// <param name="scale"></param> 3225 /// <param name="scale"></param>
2505 public void GroupResize(Vector3 scale) 3226 public void GroupResize(Vector3 scale)
2506 { 3227 {
2507// m_log.DebugFormat(
2508// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2509
2510 RootPart.StoreUndoState(true);
2511
2512 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3228 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2513 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3229 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
2514 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); 3230 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
@@ -2533,7 +3249,6 @@ namespace OpenSim.Region.Framework.Scenes
2533 SceneObjectPart obPart = parts[i]; 3249 SceneObjectPart obPart = parts[i];
2534 if (obPart.UUID != m_rootPart.UUID) 3250 if (obPart.UUID != m_rootPart.UUID)
2535 { 3251 {
2536// obPart.IgnoreUndoUpdate = true;
2537 Vector3 oldSize = new Vector3(obPart.Scale); 3252 Vector3 oldSize = new Vector3(obPart.Scale);
2538 3253
2539 float f = 1.0f; 3254 float f = 1.0f;
@@ -2597,8 +3312,6 @@ namespace OpenSim.Region.Framework.Scenes
2597 z *= a; 3312 z *= a;
2598 } 3313 }
2599 } 3314 }
2600
2601// obPart.IgnoreUndoUpdate = false;
2602 } 3315 }
2603 } 3316 }
2604 } 3317 }
@@ -2608,9 +3321,7 @@ namespace OpenSim.Region.Framework.Scenes
2608 prevScale.Y *= y; 3321 prevScale.Y *= y;
2609 prevScale.Z *= z; 3322 prevScale.Z *= z;
2610 3323
2611// RootPart.IgnoreUndoUpdate = true;
2612 RootPart.Resize(prevScale); 3324 RootPart.Resize(prevScale);
2613// RootPart.IgnoreUndoUpdate = false;
2614 3325
2615 parts = m_parts.GetArray(); 3326 parts = m_parts.GetArray();
2616 for (int i = 0; i < parts.Length; i++) 3327 for (int i = 0; i < parts.Length; i++)
@@ -2619,8 +3330,6 @@ namespace OpenSim.Region.Framework.Scenes
2619 3330
2620 if (obPart.UUID != m_rootPart.UUID) 3331 if (obPart.UUID != m_rootPart.UUID)
2621 { 3332 {
2622 obPart.IgnoreUndoUpdate = true;
2623
2624 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3333 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2625 currentpos.X *= x; 3334 currentpos.X *= x;
2626 currentpos.Y *= y; 3335 currentpos.Y *= y;
@@ -2633,16 +3342,12 @@ namespace OpenSim.Region.Framework.Scenes
2633 3342
2634 obPart.Resize(newSize); 3343 obPart.Resize(newSize);
2635 obPart.UpdateOffSet(currentpos); 3344 obPart.UpdateOffSet(currentpos);
2636
2637 obPart.IgnoreUndoUpdate = false;
2638 } 3345 }
2639 3346
2640// obPart.IgnoreUndoUpdate = false; 3347 HasGroupChanged = true;
2641// obPart.StoreUndoState(); 3348 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3349 ScheduleGroupForTerseUpdate();
2642 } 3350 }
2643
2644// m_log.DebugFormat(
2645// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
2646 } 3351 }
2647 3352
2648 #endregion 3353 #endregion
@@ -2655,14 +3360,6 @@ namespace OpenSim.Region.Framework.Scenes
2655 /// <param name="pos"></param> 3360 /// <param name="pos"></param>
2656 public void UpdateGroupPosition(Vector3 pos) 3361 public void UpdateGroupPosition(Vector3 pos)
2657 { 3362 {
2658// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2659
2660 RootPart.StoreUndoState(true);
2661
2662// SceneObjectPart[] parts = m_parts.GetArray();
2663// for (int i = 0; i < parts.Length; i++)
2664// parts[i].StoreUndoState();
2665
2666 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3363 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2667 { 3364 {
2668 if (IsAttachment) 3365 if (IsAttachment)
@@ -2694,21 +3391,17 @@ namespace OpenSim.Region.Framework.Scenes
2694 /// </summary> 3391 /// </summary>
2695 /// <param name="pos"></param> 3392 /// <param name="pos"></param>
2696 /// <param name="localID"></param> 3393 /// <param name="localID"></param>
3394 ///
3395
2697 public void UpdateSinglePosition(Vector3 pos, uint localID) 3396 public void UpdateSinglePosition(Vector3 pos, uint localID)
2698 { 3397 {
2699 SceneObjectPart part = GetChildPart(localID); 3398 SceneObjectPart part = GetChildPart(localID);
2700 3399
2701// SceneObjectPart[] parts = m_parts.GetArray();
2702// for (int i = 0; i < parts.Length; i++)
2703// parts[i].StoreUndoState();
2704
2705 if (part != null) 3400 if (part != null)
2706 { 3401 {
2707// m_log.DebugFormat( 3402// unlock parts position change
2708// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3403 if (m_rootPart.PhysActor != null)
2709 3404 m_rootPart.PhysActor.Building = true;
2710 part.StoreUndoState(false);
2711 part.IgnoreUndoUpdate = true;
2712 3405
2713 if (part.UUID == m_rootPart.UUID) 3406 if (part.UUID == m_rootPart.UUID)
2714 { 3407 {
@@ -2719,8 +3412,10 @@ namespace OpenSim.Region.Framework.Scenes
2719 part.UpdateOffSet(pos); 3412 part.UpdateOffSet(pos);
2720 } 3413 }
2721 3414
3415 if (m_rootPart.PhysActor != null)
3416 m_rootPart.PhysActor.Building = false;
3417
2722 HasGroupChanged = true; 3418 HasGroupChanged = true;
2723 part.IgnoreUndoUpdate = false;
2724 } 3419 }
2725 } 3420 }
2726 3421
@@ -2730,13 +3425,7 @@ namespace OpenSim.Region.Framework.Scenes
2730 /// <param name="pos"></param> 3425 /// <param name="pos"></param>
2731 public void UpdateRootPosition(Vector3 pos) 3426 public void UpdateRootPosition(Vector3 pos)
2732 { 3427 {
2733// m_log.DebugFormat( 3428 // needs to be called with phys building true
2734// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
2735
2736// SceneObjectPart[] parts = m_parts.GetArray();
2737// for (int i = 0; i < parts.Length; i++)
2738// parts[i].StoreUndoState();
2739
2740 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3429 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2741 Vector3 oldPos = 3430 Vector3 oldPos =
2742 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3431 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
@@ -2759,7 +3448,14 @@ namespace OpenSim.Region.Framework.Scenes
2759 AbsolutePosition = newPos; 3448 AbsolutePosition = newPos;
2760 3449
2761 HasGroupChanged = true; 3450 HasGroupChanged = true;
2762 ScheduleGroupForTerseUpdate(); 3451 if (m_rootPart.Undoing)
3452 {
3453 ScheduleGroupForFullUpdate();
3454 }
3455 else
3456 {
3457 ScheduleGroupForTerseUpdate();
3458 }
2763 } 3459 }
2764 3460
2765 #endregion 3461 #endregion
@@ -2772,17 +3468,6 @@ namespace OpenSim.Region.Framework.Scenes
2772 /// <param name="rot"></param> 3468 /// <param name="rot"></param>
2773 public void UpdateGroupRotationR(Quaternion rot) 3469 public void UpdateGroupRotationR(Quaternion rot)
2774 { 3470 {
2775// m_log.DebugFormat(
2776// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
2777
2778// SceneObjectPart[] parts = m_parts.GetArray();
2779// for (int i = 0; i < parts.Length; i++)
2780// parts[i].StoreUndoState();
2781
2782 m_rootPart.StoreUndoState(true);
2783
2784 m_rootPart.UpdateRotation(rot);
2785
2786 PhysicsActor actor = m_rootPart.PhysActor; 3471 PhysicsActor actor = m_rootPart.PhysActor;
2787 if (actor != null) 3472 if (actor != null)
2788 { 3473 {
@@ -2801,16 +3486,6 @@ namespace OpenSim.Region.Framework.Scenes
2801 /// <param name="rot"></param> 3486 /// <param name="rot"></param>
2802 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3487 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
2803 { 3488 {
2804// m_log.DebugFormat(
2805// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
2806
2807// SceneObjectPart[] parts = m_parts.GetArray();
2808// for (int i = 0; i < parts.Length; i++)
2809// parts[i].StoreUndoState();
2810
2811 RootPart.StoreUndoState(true);
2812 RootPart.IgnoreUndoUpdate = true;
2813
2814 m_rootPart.UpdateRotation(rot); 3489 m_rootPart.UpdateRotation(rot);
2815 3490
2816 PhysicsActor actor = m_rootPart.PhysActor; 3491 PhysicsActor actor = m_rootPart.PhysActor;
@@ -2824,8 +3499,6 @@ namespace OpenSim.Region.Framework.Scenes
2824 3499
2825 HasGroupChanged = true; 3500 HasGroupChanged = true;
2826 ScheduleGroupForTerseUpdate(); 3501 ScheduleGroupForTerseUpdate();
2827
2828 RootPart.IgnoreUndoUpdate = false;
2829 } 3502 }
2830 3503
2831 /// <summary> 3504 /// <summary>
@@ -2836,15 +3509,12 @@ namespace OpenSim.Region.Framework.Scenes
2836 public void UpdateSingleRotation(Quaternion rot, uint localID) 3509 public void UpdateSingleRotation(Quaternion rot, uint localID)
2837 { 3510 {
2838 SceneObjectPart part = GetChildPart(localID); 3511 SceneObjectPart part = GetChildPart(localID);
2839
2840 SceneObjectPart[] parts = m_parts.GetArray(); 3512 SceneObjectPart[] parts = m_parts.GetArray();
2841 for (int i = 0; i < parts.Length; i++)
2842 parts[i].StoreUndoState();
2843 3513
2844 if (part != null) 3514 if (part != null)
2845 { 3515 {
2846// m_log.DebugFormat( 3516 if (m_rootPart.PhysActor != null)
2847// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 3517 m_rootPart.PhysActor.Building = true;
2848 3518
2849 if (part.UUID == m_rootPart.UUID) 3519 if (part.UUID == m_rootPart.UUID)
2850 { 3520 {
@@ -2854,6 +3524,9 @@ namespace OpenSim.Region.Framework.Scenes
2854 { 3524 {
2855 part.UpdateRotation(rot); 3525 part.UpdateRotation(rot);
2856 } 3526 }
3527
3528 if (m_rootPart.PhysActor != null)
3529 m_rootPart.PhysActor.Building = false;
2857 } 3530 }
2858 } 3531 }
2859 3532
@@ -2867,12 +3540,8 @@ namespace OpenSim.Region.Framework.Scenes
2867 SceneObjectPart part = GetChildPart(localID); 3540 SceneObjectPart part = GetChildPart(localID);
2868 if (part != null) 3541 if (part != null)
2869 { 3542 {
2870// m_log.DebugFormat( 3543 if (m_rootPart.PhysActor != null)
2871// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 3544 m_rootPart.PhysActor.Building = true;
2872// part.Name, part.LocalId, rot);
2873
2874 part.StoreUndoState();
2875 part.IgnoreUndoUpdate = true;
2876 3545
2877 if (part.UUID == m_rootPart.UUID) 3546 if (part.UUID == m_rootPart.UUID)
2878 { 3547 {
@@ -2885,7 +3554,8 @@ namespace OpenSim.Region.Framework.Scenes
2885 part.OffsetPosition = pos; 3554 part.OffsetPosition = pos;
2886 } 3555 }
2887 3556
2888 part.IgnoreUndoUpdate = false; 3557 if (m_rootPart.PhysActor != null)
3558 m_rootPart.PhysActor.Building = false;
2889 } 3559 }
2890 } 3560 }
2891 3561
@@ -2895,15 +3565,12 @@ namespace OpenSim.Region.Framework.Scenes
2895 /// <param name="rot"></param> 3565 /// <param name="rot"></param>
2896 public void UpdateRootRotation(Quaternion rot) 3566 public void UpdateRootRotation(Quaternion rot)
2897 { 3567 {
2898// m_log.DebugFormat( 3568 // needs to be called with phys building true
2899// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
2900// Name, LocalId, rot);
2901
2902 Quaternion axRot = rot; 3569 Quaternion axRot = rot;
2903 Quaternion oldParentRot = m_rootPart.RotationOffset; 3570 Quaternion oldParentRot = m_rootPart.RotationOffset;
2904 3571
2905 m_rootPart.StoreUndoState(); 3572 //Don't use UpdateRotation because it schedules an update prematurely
2906 m_rootPart.UpdateRotation(rot); 3573 m_rootPart.RotationOffset = rot;
2907 if (m_rootPart.PhysActor != null) 3574 if (m_rootPart.PhysActor != null)
2908 { 3575 {
2909 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset; 3576 m_rootPart.PhysActor.Orientation = m_rootPart.RotationOffset;
@@ -2916,35 +3583,135 @@ namespace OpenSim.Region.Framework.Scenes
2916 SceneObjectPart prim = parts[i]; 3583 SceneObjectPart prim = parts[i];
2917 if (prim.UUID != m_rootPart.UUID) 3584 if (prim.UUID != m_rootPart.UUID)
2918 { 3585 {
2919 prim.IgnoreUndoUpdate = true; 3586 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3587 NewRot = Quaternion.Inverse(axRot) * NewRot;
3588 prim.RotationOffset = NewRot;
3589
2920 Vector3 axPos = prim.OffsetPosition; 3590 Vector3 axPos = prim.OffsetPosition;
3591
2921 axPos *= oldParentRot; 3592 axPos *= oldParentRot;
2922 axPos *= Quaternion.Inverse(axRot); 3593 axPos *= Quaternion.Inverse(axRot);
2923 prim.OffsetPosition = axPos; 3594 prim.OffsetPosition = axPos;
2924 Quaternion primsRot = prim.RotationOffset; 3595 }
2925 Quaternion newRot = oldParentRot * primsRot; 3596 }
2926 newRot = Quaternion.Inverse(axRot) * newRot;
2927 prim.RotationOffset = newRot;
2928 prim.ScheduleTerseUpdate();
2929 prim.IgnoreUndoUpdate = false;
2930 }
2931 }
2932
2933// for (int i = 0; i < parts.Length; i++)
2934// {
2935// SceneObjectPart childpart = parts[i];
2936// if (childpart != m_rootPart)
2937// {
2938//// childpart.IgnoreUndoUpdate = false;
2939//// childpart.StoreUndoState();
2940// }
2941// }
2942 3597
2943 m_rootPart.ScheduleTerseUpdate(); 3598 HasGroupChanged = true;
3599 ScheduleGroupForFullUpdate();
3600 }
2944 3601
2945// m_log.DebugFormat( 3602 private enum updatetype :int
2946// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3603 {
2947// Name, LocalId, rot); 3604 none = 0,
3605 partterse = 1,
3606 partfull = 2,
3607 groupterse = 3,
3608 groupfull = 4
3609 }
3610
3611 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3612 {
3613 // TODO this still as excessive *.Schedule*Update()s
3614
3615 if (part != null && part.ParentGroup != null)
3616 {
3617 ObjectChangeType change = data.change;
3618 bool togroup = ((change & ObjectChangeType.Group) != 0);
3619 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
3620
3621 SceneObjectGroup group = part.ParentGroup;
3622 PhysicsActor pha = group.RootPart.PhysActor;
3623
3624 updatetype updateType = updatetype.none;
3625
3626 if (togroup)
3627 {
3628 // related to group
3629 if ((change & ObjectChangeType.Position) != 0)
3630 {
3631 group.AbsolutePosition = data.position;
3632 updateType = updatetype.groupterse;
3633 }
3634 if ((change & ObjectChangeType.Rotation) != 0)
3635 {
3636 group.RootPart.UpdateRotation(data.rotation);
3637 updateType = updatetype.none;
3638 }
3639 if ((change & ObjectChangeType.Scale) != 0)
3640 {
3641 if (pha != null)
3642 pha.Building = true;
3643
3644 group.GroupResize(data.scale);
3645 updateType = updatetype.none;
3646
3647 if (pha != null)
3648 pha.Building = false;
3649 }
3650 }
3651 else
3652 {
3653 // related to single prim in a link-set ( ie group)
3654 if (pha != null)
3655 pha.Building = true;
3656
3657 // root part is special
3658 // parts offset positions or rotations need to change also
3659
3660 if (part == group.RootPart)
3661 {
3662 if ((change & ObjectChangeType.Position) != 0)
3663 group.UpdateRootPosition(data.position);
3664 if ((change & ObjectChangeType.Rotation) != 0)
3665 group.UpdateRootRotation(data.rotation);
3666 if ((change & ObjectChangeType.Scale) != 0)
3667 part.Resize(data.scale);
3668 }
3669 else
3670 {
3671 if ((change & ObjectChangeType.Position) != 0)
3672 {
3673 part.OffsetPosition = data.position;
3674 updateType = updatetype.partterse;
3675 }
3676 if ((change & ObjectChangeType.Rotation) != 0)
3677 {
3678 part.UpdateRotation(data.rotation);
3679 updateType = updatetype.none;
3680 }
3681 if ((change & ObjectChangeType.Scale) != 0)
3682 {
3683 part.Resize(data.scale);
3684 updateType = updatetype.none;
3685 }
3686 }
3687
3688 if (pha != null)
3689 pha.Building = false;
3690 }
3691
3692 if (updateType != updatetype.none)
3693 {
3694 group.HasGroupChanged = true;
3695
3696 switch (updateType)
3697 {
3698 case updatetype.partterse:
3699 part.ScheduleTerseUpdate();
3700 break;
3701 case updatetype.partfull:
3702 part.ScheduleFullUpdate();
3703 break;
3704 case updatetype.groupterse:
3705 group.ScheduleGroupForTerseUpdate();
3706 break;
3707 case updatetype.groupfull:
3708 group.ScheduleGroupForFullUpdate();
3709 break;
3710 default:
3711 break;
3712 }
3713 }
3714 }
2948 } 3715 }
2949 3716
2950 #endregion 3717 #endregion
@@ -3168,7 +3935,6 @@ namespace OpenSim.Region.Framework.Scenes
3168 public float GetMass() 3935 public float GetMass()
3169 { 3936 {
3170 float retmass = 0f; 3937 float retmass = 0f;
3171
3172 SceneObjectPart[] parts = m_parts.GetArray(); 3938 SceneObjectPart[] parts = m_parts.GetArray();
3173 for (int i = 0; i < parts.Length; i++) 3939 for (int i = 0; i < parts.Length; i++)
3174 retmass += parts[i].GetMass(); 3940 retmass += parts[i].GetMass();
@@ -3264,6 +4030,14 @@ namespace OpenSim.Region.Framework.Scenes
3264 SetFromItemID(uuid); 4030 SetFromItemID(uuid);
3265 } 4031 }
3266 4032
4033 public void ResetOwnerChangeFlag()
4034 {
4035 ForEachPart(delegate(SceneObjectPart part)
4036 {
4037 part.ResetOwnerChangeFlag();
4038 });
4039 }
4040
3267 #endregion 4041 #endregion
3268 } 4042 }
3269} 4043}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 439b718..cfa3cd4 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.
@@ -184,6 +185,15 @@ namespace OpenSim.Region.Framework.Scenes
184 185
185 public UUID FromFolderID; 186 public UUID FromFolderID;
186 187
188 // The following two are to hold the attachment data
189 // while an object is inworld
190 [XmlIgnore]
191 public byte AttachPoint = 0;
192
193 [XmlIgnore]
194 public Vector3 AttachOffset = Vector3.Zero;
195
196 [XmlIgnore]
187 public int STATUS_ROTATE_X; 197 public int STATUS_ROTATE_X;
188 198
189 public int STATUS_ROTATE_Y; 199 public int STATUS_ROTATE_Y;
@@ -210,8 +220,7 @@ namespace OpenSim.Region.Framework.Scenes
210 220
211 public Vector3 RotationAxis = Vector3.One; 221 public Vector3 RotationAxis = Vector3.One;
212 222
213 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 223 public bool VolumeDetectActive;
214 // Certainly this must be a persistant setting finally
215 224
216 public bool IsWaitingForFirstSpinUpdatePacket; 225 public bool IsWaitingForFirstSpinUpdatePacket;
217 226
@@ -251,10 +260,10 @@ namespace OpenSim.Region.Framework.Scenes
251 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 260 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
252 private Vector3 m_sitTargetPosition; 261 private Vector3 m_sitTargetPosition;
253 private string m_sitAnimation = "SIT"; 262 private string m_sitAnimation = "SIT";
263 private bool m_occupied; // KF if any av is sitting on this prim
254 private string m_text = String.Empty; 264 private string m_text = String.Empty;
255 private string m_touchName = String.Empty; 265 private string m_touchName = String.Empty;
256 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 266 private UndoRedoState m_UndoRedo = null;
257 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5);
258 267
259 private bool m_passTouches; 268 private bool m_passTouches;
260 269
@@ -283,7 +292,16 @@ namespace OpenSim.Region.Framework.Scenes
283 protected Vector3 m_lastAcceleration; 292 protected Vector3 m_lastAcceleration;
284 protected Vector3 m_lastAngularVelocity; 293 protected Vector3 m_lastAngularVelocity;
285 protected int m_lastTerseSent; 294 protected int m_lastTerseSent;
286 295 protected float m_buoyancy = 0.0f;
296 protected Vector3 m_force;
297 protected Vector3 m_torque;
298
299 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
300 protected float m_density = 1000.0f; // in kg/m^3
301 protected float m_gravitymod = 1.0f;
302 protected float m_friction = 0.6f; // wood
303 protected float m_bounce = 0.5f; // wood
304
287 /// <summary> 305 /// <summary>
288 /// Stores media texture data 306 /// Stores media texture data
289 /// </summary> 307 /// </summary>
@@ -299,6 +317,17 @@ namespace OpenSim.Region.Framework.Scenes
299 private UUID m_collisionSound; 317 private UUID m_collisionSound;
300 private float m_collisionSoundVolume; 318 private float m_collisionSoundVolume;
301 319
320
321 private SOPVehicle m_vehicle = null;
322
323 private KeyframeMotion m_keyframeMotion = null;
324
325 public KeyframeMotion KeyframeMotion
326 {
327 get; set;
328 }
329
330
302 #endregion Fields 331 #endregion Fields
303 332
304// ~SceneObjectPart() 333// ~SceneObjectPart()
@@ -341,7 +370,7 @@ namespace OpenSim.Region.Framework.Scenes
341 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 370 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
342 Quaternion rotationOffset, Vector3 offsetPosition) : this() 371 Quaternion rotationOffset, Vector3 offsetPosition) : this()
343 { 372 {
344 m_name = "Primitive"; 373 m_name = "Object";
345 374
346 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 375 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
347 LastOwnerID = CreatorID = OwnerID = ownerID; 376 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -381,7 +410,7 @@ namespace OpenSim.Region.Framework.Scenes
381 private uint _ownerMask = (uint)PermissionMask.All; 410 private uint _ownerMask = (uint)PermissionMask.All;
382 private uint _groupMask = (uint)PermissionMask.None; 411 private uint _groupMask = (uint)PermissionMask.None;
383 private uint _everyoneMask = (uint)PermissionMask.None; 412 private uint _everyoneMask = (uint)PermissionMask.None;
384 private uint _nextOwnerMask = (uint)PermissionMask.All; 413 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
385 private PrimFlags _flags = PrimFlags.None; 414 private PrimFlags _flags = PrimFlags.None;
386 private DateTime m_expires; 415 private DateTime m_expires;
387 private DateTime m_rezzed; 416 private DateTime m_rezzed;
@@ -475,12 +504,16 @@ namespace OpenSim.Region.Framework.Scenes
475 } 504 }
476 505
477 /// <value> 506 /// <value>
478 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 507 /// Get the inventory list
479 /// </value> 508 /// </value>
480 public TaskInventoryDictionary TaskInventory 509 public TaskInventoryDictionary TaskInventory
481 { 510 {
482 get { return m_inventory.Items; } 511 get {
483 set { m_inventory.Items = value; } 512 return m_inventory.Items;
513 }
514 set {
515 m_inventory.Items = value;
516 }
484 } 517 }
485 518
486 /// <summary> 519 /// <summary>
@@ -529,19 +562,6 @@ namespace OpenSim.Region.Framework.Scenes
529 } 562 }
530 } 563 }
531 564
532 public byte Material
533 {
534 get { return (byte) m_material; }
535 set
536 {
537 m_material = (Material)value;
538 if (PhysActor != null)
539 {
540 PhysActor.SetMaterial((int)value);
541 }
542 }
543 }
544
545 public bool PassTouches 565 public bool PassTouches
546 { 566 {
547 get { return m_passTouches; } 567 get { return m_passTouches; }
@@ -624,14 +644,12 @@ namespace OpenSim.Region.Framework.Scenes
624 set { m_LoopSoundSlavePrims = value; } 644 set { m_LoopSoundSlavePrims = value; }
625 } 645 }
626 646
627
628 public Byte[] TextureAnimation 647 public Byte[] TextureAnimation
629 { 648 {
630 get { return m_TextureAnimation; } 649 get { return m_TextureAnimation; }
631 set { m_TextureAnimation = value; } 650 set { m_TextureAnimation = value; }
632 } 651 }
633 652
634
635 public Byte[] ParticleSystem 653 public Byte[] ParticleSystem
636 { 654 {
637 get { return m_particleSystem; } 655 get { return m_particleSystem; }
@@ -668,9 +686,11 @@ namespace OpenSim.Region.Framework.Scenes
668 { 686 {
669 // If this is a linkset, we don't want the physics engine mucking up our group position here. 687 // If this is a linkset, we don't want the physics engine mucking up our group position here.
670 PhysicsActor actor = PhysActor; 688 PhysicsActor actor = PhysActor;
671 if (actor != null && ParentID == 0) 689 if (ParentID == 0)
672 { 690 {
673 m_groupPosition = actor.Position; 691 if (actor != null)
692 m_groupPosition = actor.Position;
693 return m_groupPosition;
674 } 694 }
675 695
676 if (ParentGroup.IsAttachment) 696 if (ParentGroup.IsAttachment)
@@ -680,12 +700,14 @@ namespace OpenSim.Region.Framework.Scenes
680 return sp.AbsolutePosition; 700 return sp.AbsolutePosition;
681 } 701 }
682 702
703 // use root prim's group position. Physics may have updated it
704 if (ParentGroup.RootPart != this)
705 m_groupPosition = ParentGroup.RootPart.GroupPosition;
683 return m_groupPosition; 706 return m_groupPosition;
684 } 707 }
685 set 708 set
686 { 709 {
687 m_groupPosition = value; 710 m_groupPosition = value;
688
689 PhysicsActor actor = PhysActor; 711 PhysicsActor actor = PhysActor;
690 if (actor != null) 712 if (actor != null)
691 { 713 {
@@ -711,16 +733,6 @@ namespace OpenSim.Region.Framework.Scenes
711 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 733 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
712 } 734 }
713 } 735 }
714
715 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
716 if (SitTargetAvatar != UUID.Zero)
717 {
718 ScenePresence avatar;
719 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
720 {
721 avatar.ParentPosition = GetWorldPosition();
722 }
723 }
724 } 736 }
725 } 737 }
726 738
@@ -729,7 +741,7 @@ namespace OpenSim.Region.Framework.Scenes
729 get { return m_offsetPosition; } 741 get { return m_offsetPosition; }
730 set 742 set
731 { 743 {
732// StoreUndoState(); 744 Vector3 oldpos = m_offsetPosition;
733 m_offsetPosition = value; 745 m_offsetPosition = value;
734 746
735 if (ParentGroup != null && !ParentGroup.IsDeleted) 747 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -744,7 +756,22 @@ namespace OpenSim.Region.Framework.Scenes
744 if (ParentGroup.Scene != null) 756 if (ParentGroup.Scene != null)
745 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 757 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
746 } 758 }
759
760 if (!m_parentGroup.m_dupeInProgress)
761 {
762 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
763 foreach (ScenePresence av in avs)
764 {
765 if (av.ParentID == m_localId)
766 {
767 Vector3 offset = (m_offsetPosition - oldpos);
768 av.AbsolutePosition += offset;
769 av.SendAvatarDataToAllAgents();
770 }
771 }
772 }
747 } 773 }
774 TriggerScriptChangedEvent(Changed.POSITION);
748 } 775 }
749 } 776 }
750 777
@@ -793,7 +820,7 @@ namespace OpenSim.Region.Framework.Scenes
793 820
794 set 821 set
795 { 822 {
796 StoreUndoState(); 823// StoreUndoState();
797 m_rotationOffset = value; 824 m_rotationOffset = value;
798 825
799 PhysicsActor actor = PhysActor; 826 PhysicsActor actor = PhysActor;
@@ -881,7 +908,7 @@ namespace OpenSim.Region.Framework.Scenes
881 get 908 get
882 { 909 {
883 PhysicsActor actor = PhysActor; 910 PhysicsActor actor = PhysActor;
884 if ((actor != null) && actor.IsPhysical) 911 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
885 { 912 {
886 m_angularVelocity = actor.RotationalVelocity; 913 m_angularVelocity = actor.RotationalVelocity;
887 } 914 }
@@ -893,7 +920,16 @@ namespace OpenSim.Region.Framework.Scenes
893 /// <summary></summary> 920 /// <summary></summary>
894 public Vector3 Acceleration 921 public Vector3 Acceleration
895 { 922 {
896 get { return m_acceleration; } 923 get
924 {
925 PhysicsActor actor = PhysActor;
926 if (actor != null)
927 {
928 m_acceleration = actor.Acceleration;
929 }
930 return m_acceleration;
931 }
932
897 set { m_acceleration = value; } 933 set { m_acceleration = value; }
898 } 934 }
899 935
@@ -950,7 +986,10 @@ namespace OpenSim.Region.Framework.Scenes
950 public PrimitiveBaseShape Shape 986 public PrimitiveBaseShape Shape
951 { 987 {
952 get { return m_shape; } 988 get { return m_shape; }
953 set { m_shape = value;} 989 set
990 {
991 m_shape = value;
992 }
954 } 993 }
955 994
956 /// <summary> 995 /// <summary>
@@ -963,7 +1002,6 @@ namespace OpenSim.Region.Framework.Scenes
963 { 1002 {
964 if (m_shape != null) 1003 if (m_shape != null)
965 { 1004 {
966 StoreUndoState();
967 1005
968 m_shape.Scale = value; 1006 m_shape.Scale = value;
969 1007
@@ -990,6 +1028,7 @@ namespace OpenSim.Region.Framework.Scenes
990 } 1028 }
991 1029
992 public UpdateRequired UpdateFlag { get; set; } 1030 public UpdateRequired UpdateFlag { get; set; }
1031 public bool UpdatePhysRequired { get; set; }
993 1032
994 /// <summary> 1033 /// <summary>
995 /// Used for media on a prim. 1034 /// Used for media on a prim.
@@ -1030,10 +1069,7 @@ namespace OpenSim.Region.Framework.Scenes
1030 { 1069 {
1031 get 1070 get
1032 { 1071 {
1033 if (ParentGroup.IsAttachment) 1072 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1034 return GroupPosition;
1035
1036 return m_offsetPosition + m_groupPosition;
1037 } 1073 }
1038 } 1074 }
1039 1075
@@ -1203,6 +1239,13 @@ namespace OpenSim.Region.Framework.Scenes
1203 _flags = value; 1239 _flags = value;
1204 } 1240 }
1205 } 1241 }
1242
1243 [XmlIgnore]
1244 public bool IsOccupied // KF If an av is sittingon this prim
1245 {
1246 get { return m_occupied; }
1247 set { m_occupied = value; }
1248 }
1206 1249
1207 /// <summary> 1250 /// <summary>
1208 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1251 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1262,6 +1305,316 @@ namespace OpenSim.Region.Framework.Scenes
1262 set { m_collisionSoundVolume = value; } 1305 set { m_collisionSoundVolume = value; }
1263 } 1306 }
1264 1307
1308 public float Buoyancy
1309 {
1310 get
1311 {
1312 if (ParentGroup.RootPart == this)
1313 return m_buoyancy;
1314
1315 return ParentGroup.RootPart.Buoyancy;
1316 }
1317 set
1318 {
1319 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1320 {
1321 ParentGroup.RootPart.Buoyancy = value;
1322 return;
1323 }
1324 m_buoyancy = value;
1325 if (PhysActor != null)
1326 PhysActor.Buoyancy = value;
1327 }
1328 }
1329
1330 public Vector3 Force
1331 {
1332 get
1333 {
1334 if (ParentGroup.RootPart == this)
1335 return m_force;
1336
1337 return ParentGroup.RootPart.Force;
1338 }
1339
1340 set
1341 {
1342 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1343 {
1344 ParentGroup.RootPart.Force = value;
1345 return;
1346 }
1347 m_force = value;
1348 if (PhysActor != null)
1349 PhysActor.Force = value;
1350 }
1351 }
1352
1353 public Vector3 Torque
1354 {
1355 get
1356 {
1357 if (ParentGroup.RootPart == this)
1358 return m_torque;
1359
1360 return ParentGroup.RootPart.Torque;
1361 }
1362
1363 set
1364 {
1365 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1366 {
1367 ParentGroup.RootPart.Torque = value;
1368 return;
1369 }
1370 m_torque = value;
1371 if (PhysActor != null)
1372 PhysActor.Torque = value;
1373 }
1374 }
1375
1376 public byte Material
1377 {
1378 get { return (byte)m_material; }
1379 set
1380 {
1381 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1382 {
1383 bool update = false;
1384
1385 if (m_material != (Material)value)
1386 {
1387 update = true;
1388 m_material = (Material)value;
1389 }
1390
1391 if (m_friction != SOPMaterialData.friction(m_material))
1392 {
1393 update = true;
1394 m_friction = SOPMaterialData.friction(m_material);
1395 }
1396
1397 if (m_bounce != SOPMaterialData.bounce(m_material))
1398 {
1399 update = true;
1400 m_bounce = SOPMaterialData.bounce(m_material);
1401 }
1402
1403 if (update)
1404 {
1405 if (PhysActor != null)
1406 {
1407 PhysActor.SetMaterial((int)value);
1408 }
1409 if(ParentGroup != null)
1410 ParentGroup.HasGroupChanged = true;
1411 ScheduleFullUpdateIfNone();
1412 UpdatePhysRequired = true;
1413 }
1414 }
1415 }
1416 }
1417
1418 // not a propriety to move to methods place later
1419 private bool HasMesh()
1420 {
1421 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1422 return true;
1423 return false;
1424 }
1425
1426 // not a propriety to move to methods place later
1427 public byte DefaultPhysicsShapeType()
1428 {
1429 byte type;
1430
1431 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1432 type = (byte)PhysShapeType.convex;
1433 else
1434 type = (byte)PhysShapeType.prim;
1435
1436 return type;
1437 }
1438
1439 [XmlIgnore]
1440 public bool UsesComplexCost
1441 {
1442 get
1443 {
1444 byte pst = PhysicsShapeType;
1445 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1446 return true;
1447 return false;
1448 }
1449 }
1450
1451 [XmlIgnore]
1452 public float PhysicsCost
1453 {
1454 get
1455 {
1456 if(PhysicsShapeType == (byte)PhysShapeType.none)
1457 return 0;
1458
1459 float cost = 0.1f;
1460 if (PhysActor != null)
1461// cost += PhysActor.Cost;
1462
1463 if ((Flags & PrimFlags.Physics) != 0)
1464 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1465 return cost;
1466 }
1467 }
1468
1469 [XmlIgnore]
1470 public float StreamingCost
1471 {
1472 get
1473 {
1474
1475
1476 return 0.1f;
1477 }
1478 }
1479
1480 [XmlIgnore]
1481 public float SimulationCost
1482 {
1483 get
1484 {
1485 // ignoring scripts. Don't like considering them for this
1486 if((Flags & PrimFlags.Physics) != 0)
1487 return 1.0f;
1488
1489 return 0.5f;
1490 }
1491 }
1492
1493 public byte PhysicsShapeType
1494 {
1495 get { return m_physicsShapeType; }
1496 set
1497 {
1498 byte oldv = m_physicsShapeType;
1499
1500 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1501 {
1502 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1503 m_physicsShapeType = DefaultPhysicsShapeType();
1504 else
1505 m_physicsShapeType = value;
1506 }
1507 else
1508 m_physicsShapeType = DefaultPhysicsShapeType();
1509
1510 if (m_physicsShapeType != oldv && ParentGroup != null)
1511 {
1512 if (m_physicsShapeType == (byte)PhysShapeType.none)
1513 {
1514 if (PhysActor != null)
1515 {
1516 Velocity = new Vector3(0, 0, 0);
1517 Acceleration = new Vector3(0, 0, 0);
1518 if (ParentGroup.RootPart == this)
1519 AngularVelocity = new Vector3(0, 0, 0);
1520 ParentGroup.Scene.RemovePhysicalPrim(1);
1521 RemoveFromPhysics();
1522 }
1523 }
1524 else if (PhysActor == null)
1525 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1526 else
1527 {
1528 PhysActor.PhysicsShapeType = m_physicsShapeType;
1529 if (Shape.SculptEntry)
1530 CheckSculptAndLoad();
1531 }
1532
1533 if (ParentGroup != null)
1534 ParentGroup.HasGroupChanged = true;
1535 }
1536
1537 if (m_physicsShapeType != value)
1538 {
1539 UpdatePhysRequired = true;
1540 }
1541 }
1542 }
1543
1544 public float Density // in kg/m^3
1545 {
1546 get { return m_density; }
1547 set
1548 {
1549 if (value >=1 && value <= 22587.0)
1550 {
1551 m_density = value;
1552 UpdatePhysRequired = true;
1553 }
1554
1555 ScheduleFullUpdateIfNone();
1556
1557 if (ParentGroup != null)
1558 ParentGroup.HasGroupChanged = true;
1559 }
1560 }
1561
1562 public float GravityModifier
1563 {
1564 get { return m_gravitymod; }
1565 set
1566 {
1567 if( value >= -1 && value <=28.0f)
1568 {
1569 m_gravitymod = value;
1570 UpdatePhysRequired = true;
1571 }
1572
1573 ScheduleFullUpdateIfNone();
1574
1575 if (ParentGroup != null)
1576 ParentGroup.HasGroupChanged = true;
1577
1578 }
1579 }
1580
1581 public float Friction
1582 {
1583 get { return m_friction; }
1584 set
1585 {
1586 if (value >= 0 && value <= 255.0f)
1587 {
1588 m_friction = value;
1589 UpdatePhysRequired = true;
1590 }
1591
1592 ScheduleFullUpdateIfNone();
1593
1594 if (ParentGroup != null)
1595 ParentGroup.HasGroupChanged = true;
1596 }
1597 }
1598
1599 public float Bounciness
1600 {
1601 get { return m_bounce; }
1602 set
1603 {
1604 if (value >= 0 && value <= 1.0f)
1605 {
1606 m_bounce = value;
1607 UpdatePhysRequired = true;
1608 }
1609
1610 ScheduleFullUpdateIfNone();
1611
1612 if (ParentGroup != null)
1613 ParentGroup.HasGroupChanged = true;
1614 }
1615 }
1616
1617
1265 #endregion Public Properties with only Get 1618 #endregion Public Properties with only Get
1266 1619
1267 private uint ApplyMask(uint val, bool set, uint mask) 1620 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1437,20 +1790,24 @@ namespace OpenSim.Region.Framework.Scenes
1437 /// </summary> 1790 /// </summary>
1438 /// <param name="impulsei">Vector force</param> 1791 /// <param name="impulsei">Vector force</param>
1439 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1792 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1440 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1793
1794 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1795 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1441 { 1796 {
1442 Vector3 impulse = impulsei; 1797 Vector3 torque = torquei;
1443 1798
1444 if (localGlobalTF) 1799 if (localGlobalTF)
1445 { 1800 {
1801/*
1446 Quaternion grot = GetWorldRotation(); 1802 Quaternion grot = GetWorldRotation();
1447 Quaternion AXgrot = grot; 1803 Quaternion AXgrot = grot;
1448 Vector3 AXimpulsei = impulsei; 1804 Vector3 AXimpulsei = impulsei;
1449 Vector3 newimpulse = AXimpulsei * AXgrot; 1805 Vector3 newimpulse = AXimpulsei * AXgrot;
1450 impulse = newimpulse; 1806 */
1807 torque *= GetWorldRotation();
1451 } 1808 }
1452 1809
1453 ParentGroup.setAngularImpulse(impulse); 1810 Torque = torque;
1454 } 1811 }
1455 1812
1456 /// <summary> 1813 /// <summary>
@@ -1458,18 +1815,19 @@ namespace OpenSim.Region.Framework.Scenes
1458 /// </summary> 1815 /// </summary>
1459 /// <param name="rootObjectFlags"></param> 1816 /// <param name="rootObjectFlags"></param>
1460 /// <param name="VolumeDetectActive"></param> 1817 /// <param name="VolumeDetectActive"></param>
1461 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 1818
1819 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive, bool building)
1462 { 1820 {
1463 if (!ParentGroup.Scene.CollidablePrims) 1821 if (!ParentGroup.Scene.CollidablePrims)
1464 return; 1822 return;
1465 1823
1466// m_log.DebugFormat( 1824 if (PhysicsShapeType == (byte)PhysShapeType.none)
1467// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 1825 return;
1468// Name, LocalId, UUID, m_physicalPrim);
1469 1826
1470 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 1827 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0;
1471 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 1828 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0;
1472 1829
1830
1473 if (IsJoint()) 1831 if (IsJoint())
1474 { 1832 {
1475 DoPhysicsPropertyUpdate(isPhysical, true); 1833 DoPhysicsPropertyUpdate(isPhysical, true);
@@ -1477,16 +1835,19 @@ namespace OpenSim.Region.Framework.Scenes
1477 else 1835 else
1478 { 1836 {
1479 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 1837 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored
1480 if (VolumeDetectActive) 1838// if (VolumeDetectActive)
1481 isPhantom = false; 1839// isPhantom = false;
1482 1840
1483 // Added clarification.. since A rigid body is an object that you can kick around, etc. 1841 // Added clarification.. since A rigid body is an object that you can kick around, etc.
1484 bool RigidBody = isPhysical && !isPhantom; 1842// bool RigidBody = isPhysical && !isPhantom;
1485 1843
1486 // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition 1844 // The only time the physics scene shouldn't know about the prim is if it's phantom or an attachment, which is phantom by definition
1487 // or flexible 1845 // or flexible
1488 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible)) 1846 // if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1847 if ((!isPhantom || isPhysical || VolumeDetectActive) && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1489 { 1848 {
1849 Vector3 velocity = Velocity;
1850 Vector3 rotationalVelocity = AngularVelocity;
1490 try 1851 try
1491 { 1852 {
1492 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape( 1853 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
@@ -1494,8 +1855,10 @@ namespace OpenSim.Region.Framework.Scenes
1494 Shape, 1855 Shape,
1495 AbsolutePosition, 1856 AbsolutePosition,
1496 Scale, 1857 Scale,
1497 RotationOffset, 1858 GetWorldRotation(),
1498 RigidBody, 1859 isPhysical,
1860 isPhantom,
1861 PhysicsShapeType,
1499 m_localId); 1862 m_localId);
1500 } 1863 }
1501 catch 1864 catch
@@ -1509,8 +1872,30 @@ namespace OpenSim.Region.Framework.Scenes
1509 { 1872 {
1510 PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 1873 PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
1511 PhysActor.SetMaterial(Material); 1874 PhysActor.SetMaterial(Material);
1512 DoPhysicsPropertyUpdate(RigidBody, true); 1875
1513 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); 1876 // if root part apply vehicle
1877 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
1878 m_vehicle.SetVehicle(PhysActor);
1879
1880 DoPhysicsPropertyUpdate(isPhysical, true);
1881 if(VolumeDetectActive) // change if not the default only
1882 PhysActor.SetVolumeDetect(1);
1883
1884 if (!building)
1885 PhysActor.Building = false;
1886
1887 Velocity = velocity;
1888 AngularVelocity = rotationalVelocity;
1889 PhysActor.Velocity = velocity;
1890 PhysActor.RotationalVelocity = rotationalVelocity;
1891
1892 // if not vehicle and root part apply force and torque
1893 if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
1894 && LocalId == ParentGroup.RootPart.LocalId)
1895 {
1896 PhysActor.Force = Force;
1897 PhysActor.Torque = Torque;
1898 }
1514 } 1899 }
1515 } 1900 }
1516 } 1901 }
@@ -1564,6 +1949,11 @@ namespace OpenSim.Region.Framework.Scenes
1564 dupe.Category = Category; 1949 dupe.Category = Category;
1565 dupe.m_rezzed = m_rezzed; 1950 dupe.m_rezzed = m_rezzed;
1566 1951
1952 dupe.m_UndoRedo = null;
1953
1954 dupe.IgnoreUndoUpdate = false;
1955 dupe.Undoing = false;
1956
1567 dupe.m_inventory = new SceneObjectPartInventory(dupe); 1957 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1568 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 1958 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1569 1959
@@ -1579,6 +1969,7 @@ namespace OpenSim.Region.Framework.Scenes
1579 1969
1580 // Move afterwards ResetIDs as it clears the localID 1970 // Move afterwards ResetIDs as it clears the localID
1581 dupe.LocalId = localID; 1971 dupe.LocalId = localID;
1972
1582 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1973 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1583 dupe.LastOwnerID = OwnerID; 1974 dupe.LastOwnerID = OwnerID;
1584 1975
@@ -1598,6 +1989,9 @@ namespace OpenSim.Region.Framework.Scenes
1598 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 1989 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1599 } 1990 }
1600 1991
1992 if (dupe.PhysActor != null)
1993 dupe.PhysActor.LocalID = localID;
1994
1601 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 1995 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1602 1996
1603// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 1997// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1735,63 +2129,63 @@ namespace OpenSim.Region.Framework.Scenes
1735 { 2129 {
1736 if (UsePhysics != PhysActor.IsPhysical || isNew) 2130 if (UsePhysics != PhysActor.IsPhysical || isNew)
1737 { 2131 {
1738 if (PhysActor.IsPhysical) // implies UsePhysics==false for this block 2132 if (PhysActor.IsPhysical)
1739 { 2133 {
1740 if (!isNew) 2134 if (!isNew) // implies UsePhysics==false for this block
2135 {
1741 ParentGroup.Scene.RemovePhysicalPrim(1); 2136 ParentGroup.Scene.RemovePhysicalPrim(1);
1742 2137
1743 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2138 Velocity = new Vector3(0, 0, 0);
1744 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds; 2139 Acceleration = new Vector3(0, 0, 0);
1745 PhysActor.delink(); 2140 if (ParentGroup.RootPart == this)
2141 AngularVelocity = new Vector3(0, 0, 0);
1746 2142
1747 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2143 if (PhysActor.Phantom)
1748 { 2144 {
1749 // destroy all joints connected to this now deactivated body 2145 RemoveFromPhysics();
1750 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(PhysActor); 2146 return;
1751 } 2147 }
1752 2148
1753 // stop client-side interpolation of all joint proxy objects that have just been deleted 2149 PhysActor.IsPhysical = UsePhysics;
1754 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2150 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1755 // which stops client-side interpolation of deactivated joint proxy objects. 2151 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds;
2152 PhysActor.delink();
2153 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2154 {
2155 // destroy all joints connected to this now deactivated body
2156 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(PhysActor);
2157 }
2158 }
1756 } 2159 }
1757 2160
1758 if (!UsePhysics && !isNew) 2161 if (PhysActor.IsPhysical != UsePhysics)
1759 { 2162 PhysActor.IsPhysical = UsePhysics;
1760 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1761 // prim still has velocity and continues to interpolate its position along the old
1762 // velocity-vector.
1763 Velocity = new Vector3(0, 0, 0);
1764 Acceleration = new Vector3(0, 0, 0);
1765 AngularVelocity = new Vector3(0, 0, 0);
1766 //RotationalVelocity = new Vector3(0, 0, 0);
1767 }
1768 2163
1769 PhysActor.IsPhysical = UsePhysics; 2164 if (UsePhysics)
2165 {
2166 if (ParentGroup.RootPart.KeyframeMotion != null)
2167 ParentGroup.RootPart.KeyframeMotion.Stop();
2168 ParentGroup.RootPart.KeyframeMotion = null;
2169 ParentGroup.Scene.AddPhysicalPrim(1);
1770 2170
1771 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2171 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1772 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2172 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1773 /// that's not wholesome. Had to make Scene public
1774 //PhysActor = null;
1775 2173
1776 if ((Flags & PrimFlags.Phantom) == 0) 2174 if (ParentID != 0 && ParentID != LocalId)
1777 {
1778 if (UsePhysics)
1779 { 2175 {
1780 ParentGroup.Scene.AddPhysicalPrim(1); 2176 if (ParentGroup.RootPart.PhysActor != null)
1781
1782 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1783 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1784 if (ParentID != 0 && ParentID != LocalId)
1785 { 2177 {
1786 if (ParentGroup.RootPart.PhysActor != null) 2178 PhysActor.link(ParentGroup.RootPart.PhysActor);
1787 {
1788 PhysActor.link(ParentGroup.RootPart.PhysActor);
1789 }
1790 } 2179 }
1791 } 2180 }
1792 } 2181 }
1793 } 2182 }
1794 2183
2184 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2185 if (PhysActor.Phantom != phan)
2186 PhysActor.Phantom = phan;
2187
2188
1795 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2189 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
1796 // mesh data. 2190 // mesh data.
1797 if (Shape.SculptEntry) 2191 if (Shape.SculptEntry)
@@ -1924,10 +2318,7 @@ namespace OpenSim.Region.Framework.Scenes
1924 2318
1925 public Vector3 GetForce() 2319 public Vector3 GetForce()
1926 { 2320 {
1927 if (PhysActor != null) 2321 return Force;
1928 return PhysActor.Force;
1929 else
1930 return Vector3.Zero;
1931 } 2322 }
1932 2323
1933 /// <summary> 2324 /// <summary>
@@ -2561,9 +2952,9 @@ namespace OpenSim.Region.Framework.Scenes
2561 Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0); 2952 Vector3 newpos = new Vector3(PhysActor.Position.GetBytes(), 0);
2562 2953
2563 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2954 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2564 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2955 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2565 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2956 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2566 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2957 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2567 { 2958 {
2568 ParentGroup.AbsolutePosition = newpos; 2959 ParentGroup.AbsolutePosition = newpos;
2569 return; 2960 return;
@@ -2584,17 +2975,18 @@ namespace OpenSim.Region.Framework.Scenes
2584 //Trys to fetch sound id from prim's inventory. 2975 //Trys to fetch sound id from prim's inventory.
2585 //Prim's inventory doesn't support non script items yet 2976 //Prim's inventory doesn't support non script items yet
2586 2977
2587 lock (TaskInventory) 2978 TaskInventory.LockItemsForRead(true);
2979
2980 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2588 { 2981 {
2589 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2982 if (item.Value.Name == sound)
2590 { 2983 {
2591 if (item.Value.Name == sound) 2984 soundID = item.Value.ItemID;
2592 { 2985 break;
2593 soundID = item.Value.ItemID;
2594 break;
2595 }
2596 } 2986 }
2597 } 2987 }
2988
2989 TaskInventory.LockItemsForRead(false);
2598 } 2990 }
2599 2991
2600 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2992 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2715,6 +3107,19 @@ namespace OpenSim.Region.Framework.Scenes
2715 APIDTarget = Quaternion.Identity; 3107 APIDTarget = Quaternion.Identity;
2716 } 3108 }
2717 3109
3110
3111
3112 public void ScheduleFullUpdateIfNone()
3113 {
3114 if (ParentGroup == null)
3115 return;
3116
3117// ??? ParentGroup.HasGroupChanged = true;
3118
3119 if (UpdateFlag != UpdateRequired.FULL)
3120 ScheduleFullUpdate();
3121 }
3122
2718 /// <summary> 3123 /// <summary>
2719 /// Schedules this prim for a full update 3124 /// Schedules this prim for a full update
2720 /// </summary> 3125 /// </summary>
@@ -2914,8 +3319,8 @@ namespace OpenSim.Region.Framework.Scenes
2914 { 3319 {
2915 const float ROTATION_TOLERANCE = 0.01f; 3320 const float ROTATION_TOLERANCE = 0.01f;
2916 const float VELOCITY_TOLERANCE = 0.001f; 3321 const float VELOCITY_TOLERANCE = 0.001f;
2917 const float POSITION_TOLERANCE = 0.05f; 3322 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2918 const int TIME_MS_TOLERANCE = 3000; 3323 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2919 3324
2920 switch (UpdateFlag) 3325 switch (UpdateFlag)
2921 { 3326 {
@@ -2977,17 +3382,16 @@ namespace OpenSim.Region.Framework.Scenes
2977 if (!UUID.TryParse(sound, out soundID)) 3382 if (!UUID.TryParse(sound, out soundID))
2978 { 3383 {
2979 // search sound file from inventory 3384 // search sound file from inventory
2980 lock (TaskInventory) 3385 TaskInventory.LockItemsForRead(true);
3386 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2981 { 3387 {
2982 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3388 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2983 { 3389 {
2984 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3390 soundID = item.Value.ItemID;
2985 { 3391 break;
2986 soundID = item.Value.ItemID;
2987 break;
2988 }
2989 } 3392 }
2990 } 3393 }
3394 TaskInventory.LockItemsForRead(false);
2991 } 3395 }
2992 3396
2993 if (soundID == UUID.Zero) 3397 if (soundID == UUID.Zero)
@@ -3072,10 +3476,13 @@ namespace OpenSim.Region.Framework.Scenes
3072 3476
3073 public void SetBuoyancy(float fvalue) 3477 public void SetBuoyancy(float fvalue)
3074 { 3478 {
3479 Buoyancy = fvalue;
3480/*
3075 if (PhysActor != null) 3481 if (PhysActor != null)
3076 { 3482 {
3077 PhysActor.Buoyancy = fvalue; 3483 PhysActor.Buoyancy = fvalue;
3078 } 3484 }
3485 */
3079 } 3486 }
3080 3487
3081 public void SetDieAtEdge(bool p) 3488 public void SetDieAtEdge(bool p)
@@ -3103,23 +3510,83 @@ namespace OpenSim.Region.Framework.Scenes
3103 3510
3104 public void SetForce(Vector3 force) 3511 public void SetForce(Vector3 force)
3105 { 3512 {
3513 Force = force;
3514/*
3106 if (PhysActor != null) 3515 if (PhysActor != null)
3107 { 3516 {
3108 PhysActor.Force = force; 3517 PhysActor.Force = force;
3109 } 3518 }
3519 */
3520 }
3521
3522 public SOPVehicle sopVehicle
3523 {
3524 get
3525 {
3526 return m_vehicle;
3527 }
3528 set
3529 {
3530 m_vehicle = value;
3531 }
3532 }
3533
3534
3535 public int VehicleType
3536 {
3537 get
3538 {
3539 if (m_vehicle == null)
3540 return (int)Vehicle.TYPE_NONE;
3541 else
3542 return (int)m_vehicle.Type;
3543 }
3544 set
3545 {
3546 SetVehicleType(value);
3547 }
3110 } 3548 }
3111 3549
3112 public void SetVehicleType(int type) 3550 public void SetVehicleType(int type)
3113 { 3551 {
3114 if (PhysActor != null) 3552 m_vehicle = null;
3553
3554 if (type == (int)Vehicle.TYPE_NONE)
3555 {
3556 if (_parentID ==0 && PhysActor != null)
3557 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3558 return;
3559 }
3560 m_vehicle = new SOPVehicle();
3561 m_vehicle.ProcessTypeChange((Vehicle)type);
3562 {
3563 if (_parentID ==0 && PhysActor != null)
3564 PhysActor.VehicleType = type;
3565 return;
3566 }
3567 }
3568
3569 public void SetVehicleFlags(int param, bool remove)
3570 {
3571 if (m_vehicle == null)
3572 return;
3573
3574 m_vehicle.ProcessVehicleFlags(param, remove);
3575
3576 if (_parentID ==0 && PhysActor != null)
3115 { 3577 {
3116 PhysActor.VehicleType = type; 3578 PhysActor.VehicleFlags(param, remove);
3117 } 3579 }
3118 } 3580 }
3119 3581
3120 public void SetVehicleFloatParam(int param, float value) 3582 public void SetVehicleFloatParam(int param, float value)
3121 { 3583 {
3122 if (PhysActor != null) 3584 if (m_vehicle == null)
3585 return;
3586
3587 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
3588
3589 if (_parentID == 0 && PhysActor != null)
3123 { 3590 {
3124 PhysActor.VehicleFloatParam(param, value); 3591 PhysActor.VehicleFloatParam(param, value);
3125 } 3592 }
@@ -3127,7 +3594,12 @@ namespace OpenSim.Region.Framework.Scenes
3127 3594
3128 public void SetVehicleVectorParam(int param, Vector3 value) 3595 public void SetVehicleVectorParam(int param, Vector3 value)
3129 { 3596 {
3130 if (PhysActor != null) 3597 if (m_vehicle == null)
3598 return;
3599
3600 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
3601
3602 if (_parentID == 0 && PhysActor != null)
3131 { 3603 {
3132 PhysActor.VehicleVectorParam(param, value); 3604 PhysActor.VehicleVectorParam(param, value);
3133 } 3605 }
@@ -3135,7 +3607,12 @@ namespace OpenSim.Region.Framework.Scenes
3135 3607
3136 public void SetVehicleRotationParam(int param, Quaternion rotation) 3608 public void SetVehicleRotationParam(int param, Quaternion rotation)
3137 { 3609 {
3138 if (PhysActor != null) 3610 if (m_vehicle == null)
3611 return;
3612
3613 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
3614
3615 if (_parentID == 0 && PhysActor != null)
3139 { 3616 {
3140 PhysActor.VehicleRotationParam(param, rotation); 3617 PhysActor.VehicleRotationParam(param, rotation);
3141 } 3618 }
@@ -3322,13 +3799,6 @@ namespace OpenSim.Region.Framework.Scenes
3322 hasProfileCut = hasDimple; // is it the same thing? 3799 hasProfileCut = hasDimple; // is it the same thing?
3323 } 3800 }
3324 3801
3325 public void SetVehicleFlags(int param, bool remove)
3326 {
3327 if (PhysActor != null)
3328 {
3329 PhysActor.VehicleFlags(param, remove);
3330 }
3331 }
3332 3802
3333 public void SetGroup(UUID groupID, IClientAPI client) 3803 public void SetGroup(UUID groupID, IClientAPI client)
3334 { 3804 {
@@ -3431,68 +3901,18 @@ namespace OpenSim.Region.Framework.Scenes
3431 //ParentGroup.ScheduleGroupForFullUpdate(); 3901 //ParentGroup.ScheduleGroupForFullUpdate();
3432 } 3902 }
3433 3903
3434 public void StoreUndoState() 3904 public void StoreUndoState(ObjectChangeType change)
3435 { 3905 {
3436 StoreUndoState(false); 3906 if (m_UndoRedo == null)
3437 } 3907 m_UndoRedo = new UndoRedoState(5);
3438 3908
3439 public void StoreUndoState(bool forGroup) 3909 lock (m_UndoRedo)
3440 {
3441 if (!Undoing)
3442 { 3910 {
3443 if (!IgnoreUndoUpdate) 3911 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3444 { 3912 {
3445 if (ParentGroup != null) 3913 m_UndoRedo.StoreUndo(this, change);
3446 {
3447 lock (m_undo)
3448 {
3449 if (m_undo.Count > 0)
3450 {
3451 UndoState last = m_undo.Peek();
3452 if (last != null)
3453 {
3454 // TODO: May need to fix for group comparison
3455 if (last.Compare(this))
3456 {
3457 // m_log.DebugFormat(
3458 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3459 // Name, LocalId, m_undo.Count);
3460
3461 return;
3462 }
3463 }
3464 }
3465
3466 // m_log.DebugFormat(
3467 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3468 // Name, LocalId, forGroup, m_undo.Count);
3469
3470 if (ParentGroup.GetSceneMaxUndo() > 0)
3471 {
3472 UndoState nUndo = new UndoState(this, forGroup);
3473
3474 m_undo.Push(nUndo);
3475
3476 if (m_redo.Count > 0)
3477 m_redo.Clear();
3478
3479 // m_log.DebugFormat(
3480 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3481 // Name, LocalId, forGroup, m_undo.Count);
3482 }
3483 }
3484 }
3485 } 3914 }
3486// else
3487// {
3488// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3489// }
3490 } 3915 }
3491// else
3492// {
3493// m_log.DebugFormat(
3494// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3495// }
3496 } 3916 }
3497 3917
3498 /// <summary> 3918 /// <summary>
@@ -3502,84 +3922,46 @@ namespace OpenSim.Region.Framework.Scenes
3502 { 3922 {
3503 get 3923 get
3504 { 3924 {
3505 lock (m_undo) 3925 if (m_UndoRedo == null)
3506 return m_undo.Count; 3926 return 0;
3927 return m_UndoRedo.Count;
3507 } 3928 }
3508 } 3929 }
3509 3930
3510 public void Undo() 3931 public void Undo()
3511 { 3932 {
3512 lock (m_undo) 3933 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3513 { 3934 return;
3514// m_log.DebugFormat(
3515// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3516// Name, LocalId, m_undo.Count);
3517
3518 if (m_undo.Count > 0)
3519 {
3520 UndoState goback = m_undo.Pop();
3521
3522 if (goback != null)
3523 {
3524 UndoState nUndo = null;
3525
3526 if (ParentGroup.GetSceneMaxUndo() > 0)
3527 {
3528 nUndo = new UndoState(this, goback.ForGroup);
3529 }
3530
3531 goback.PlaybackState(this);
3532
3533 if (nUndo != null)
3534 m_redo.Push(nUndo);
3535 }
3536 }
3537 3935
3538// m_log.DebugFormat( 3936 lock (m_UndoRedo)
3539// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3937 {
3540// Name, LocalId, m_undo.Count); 3938 Undoing = true;
3939 m_UndoRedo.Undo(this);
3940 Undoing = false;
3541 } 3941 }
3542 } 3942 }
3543 3943
3544 public void Redo() 3944 public void Redo()
3545 { 3945 {
3546 lock (m_undo) 3946 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3547 { 3947 return;
3548// m_log.DebugFormat(
3549// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3550// Name, LocalId, m_redo.Count);
3551
3552 if (m_redo.Count > 0)
3553 {
3554 UndoState gofwd = m_redo.Pop();
3555
3556 if (gofwd != null)
3557 {
3558 if (ParentGroup.GetSceneMaxUndo() > 0)
3559 {
3560 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3561
3562 m_undo.Push(nUndo);
3563 }
3564
3565 gofwd.PlayfwdState(this);
3566 }
3567 3948
3568// m_log.DebugFormat( 3949 lock (m_UndoRedo)
3569// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3950 {
3570// Name, LocalId, m_redo.Count); 3951 Undoing = true;
3571 } 3952 m_UndoRedo.Redo(this);
3953 Undoing = false;
3572 } 3954 }
3573 } 3955 }
3574 3956
3575 public void ClearUndoState() 3957 public void ClearUndoState()
3576 { 3958 {
3577// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3959 if (m_UndoRedo == null || Undoing)
3960 return;
3578 3961
3579 lock (m_undo) 3962 lock (m_UndoRedo)
3580 { 3963 {
3581 m_undo.Clear(); 3964 m_UndoRedo.Clear();
3582 m_redo.Clear();
3583 } 3965 }
3584 } 3966 }
3585 3967
@@ -4209,6 +4591,27 @@ namespace OpenSim.Region.Framework.Scenes
4209 } 4591 }
4210 } 4592 }
4211 4593
4594
4595 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4596 {
4597 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4598 return;
4599
4600 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4601 {
4602 PhysicsShapeType = (byte)physdata.PhysShapeType;
4603
4604 }
4605
4606 if(Density != physdata.Density)
4607 Density = physdata.Density;
4608 if(GravityModifier != physdata.GravitationModifier)
4609 GravityModifier = physdata.GravitationModifier;
4610 if(Friction != physdata.Friction)
4611 Friction = physdata.Friction;
4612 if(Bounciness != physdata.Bounce)
4613 Bounciness = physdata.Bounce;
4614 }
4212 /// <summary> 4615 /// <summary>
4213 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4616 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
4214 /// </summary> 4617 /// </summary>
@@ -4216,7 +4619,8 @@ namespace OpenSim.Region.Framework.Scenes
4216 /// <param name="SetTemporary"></param> 4619 /// <param name="SetTemporary"></param>
4217 /// <param name="SetPhantom"></param> 4620 /// <param name="SetPhantom"></param>
4218 /// <param name="SetVD"></param> 4621 /// <param name="SetVD"></param>
4219 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4622// public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD)
4623 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4220 { 4624 {
4221 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4625 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4222 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4626 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -4226,41 +4630,58 @@ namespace OpenSim.Region.Framework.Scenes
4226 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4630 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4227 return; 4631 return;
4228 4632
4633 // do this first
4634 if (building && PhysActor != null && PhysActor.Building != building)
4635 PhysActor.Building = building;
4636
4229 // Special cases for VD. VD can only be called from a script 4637 // Special cases for VD. VD can only be called from a script
4230 // and can't be combined with changes to other states. So we can rely 4638 // and can't be combined with changes to other states. So we can rely
4231 // that... 4639 // that...
4232 // ... if VD is changed, all others are not. 4640 // ... if VD is changed, all others are not.
4233 // ... if one of the others is changed, VD is not. 4641 // ... if one of the others is changed, VD is not.
4642
4643/*
4234 if (SetVD) // VD is active, special logic applies 4644 if (SetVD) // VD is active, special logic applies
4235 {
4236 // State machine logic for VolumeDetect
4237 // More logic below
4238 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4239 4645
4240 if (phanReset) // Phantom changes from on to off switch VD off too 4646 volume detection is now independent of phantom in sl
4241 { 4647
4242 SetVD = false; // Switch it of for the course of this routine 4648 {
4243 VolumeDetectActive = false; // and also permanently 4649 // State machine logic for VolumeDetect
4244 if (PhysActor != null) 4650 // More logic below
4245 PhysActor.SetVolumeDetect(0); // Let physics know about it too 4651
4246 } 4652
4247 else 4653 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4248 { 4654
4249 // If volumedetect is active we don't want phantom to be applied. 4655 if (phanReset) // Phantom changes from on to off switch VD off too
4250 // If this is a new call to VD out of the state "phantom" 4656 {
4251 // this will also cause the prim to be visible to physics 4657 SetVD = false; // Switch it of for the course of this routine
4658 VolumeDetectActive = false; // and also permanently
4659 if (PhysActor != null)
4660 PhysActor.SetVolumeDetect(0); // Let physics know about it too
4661 }
4662 else
4663 {
4664 // If volumedetect is active we don't want phantom to be applied.
4665 // If this is a new call to VD out of the state "phantom"
4666 // this will also cause the prim to be visible to physics
4252 SetPhantom = false; 4667 SetPhantom = false;
4253 } 4668 }
4669 }
4670 else if (wasVD)
4671 {
4672 // Correspondingly, if VD is turned off, also turn off phantom
4673 SetPhantom = false;
4254 } 4674 }
4255 4675
4256 if (UsePhysics && IsJoint()) 4676 if (UsePhysics && IsJoint())
4257 { 4677 {
4258 SetPhantom = true; 4678 SetPhantom = true;
4259 } 4679 }
4260 4680*/
4261 if (UsePhysics) 4681 if (UsePhysics)
4262 { 4682 {
4263 AddFlag(PrimFlags.Physics); 4683 AddFlag(PrimFlags.Physics);
4684/*
4264 if (!wasUsingPhysics) 4685 if (!wasUsingPhysics)
4265 { 4686 {
4266 DoPhysicsPropertyUpdate(UsePhysics, false); 4687 DoPhysicsPropertyUpdate(UsePhysics, false);
@@ -4273,78 +4694,100 @@ namespace OpenSim.Region.Framework.Scenes
4273 } 4694 }
4274 } 4695 }
4275 } 4696 }
4697 */
4276 } 4698 }
4277 else 4699 else
4278 { 4700 {
4279 RemFlag(PrimFlags.Physics); 4701 RemFlag(PrimFlags.Physics);
4702/*
4280 if (wasUsingPhysics) 4703 if (wasUsingPhysics)
4281 { 4704 {
4282 DoPhysicsPropertyUpdate(UsePhysics, false); 4705 DoPhysicsPropertyUpdate(UsePhysics, false);
4283 } 4706 }
4284 } 4707*/
4708 }
4285 4709
4286 if (SetPhantom 4710 if (SetPhantom)
4287 || ParentGroup.IsAttachment 4711 AddFlag(PrimFlags.Phantom);
4712 else
4713 RemFlag(PrimFlags.Phantom);
4714
4715 if ((SetPhantom && !UsePhysics) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4288 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints 4716 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4289 { 4717 {
4290 AddFlag(PrimFlags.Phantom); 4718// AddFlag(PrimFlags.Phantom);
4719
4720 Velocity = new Vector3(0, 0, 0);
4721 Acceleration = new Vector3(0, 0, 0);
4722 if (ParentGroup.RootPart == this)
4723 AngularVelocity = new Vector3(0, 0, 0);
4291 4724
4292 if (PhysActor != null) 4725 if (PhysActor != null)
4726 {
4727 ParentGroup.Scene.RemovePhysicalPrim(1);
4293 RemoveFromPhysics(); 4728 RemoveFromPhysics();
4729 }
4294 } 4730 }
4295 else // Not phantom 4731 else
4296 { 4732 {
4297 RemFlag(PrimFlags.Phantom);
4298
4299 if (ParentGroup.Scene == null) 4733 if (ParentGroup.Scene == null)
4300 return; 4734 return;
4301 4735
4302 if (ParentGroup.Scene.CollidablePrims && PhysActor == null) 4736 if (ParentGroup.Scene.CollidablePrims)
4303 { 4737 {
4304 // It's not phantom anymore. So make sure the physics engine get's knowledge of it 4738 if (PhysActor == null)
4305 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4306 string.Format("{0}/{1}", Name, UUID),
4307 Shape,
4308 AbsolutePosition,
4309 Scale,
4310 RotationOffset,
4311 UsePhysics,
4312 m_localId);
4313
4314 PhysActor.SetMaterial(Material);
4315 DoPhysicsPropertyUpdate(UsePhysics, true);
4316
4317 if (!ParentGroup.IsDeleted)
4318 { 4739 {
4319 if (LocalId == ParentGroup.RootPart.LocalId) 4740 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4741 string.Format("{0}/{1}", Name, UUID),
4742 Shape,
4743 AbsolutePosition,
4744 Scale,
4745 GetWorldRotation(), //physics wants world rotation like all other functions send
4746 UsePhysics,
4747 SetPhantom,
4748 PhysicsShapeType,
4749 m_localId);
4750
4751 PhysActor.SetMaterial(Material);
4752
4753 // if root part apply vehicle
4754 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
4755 m_vehicle.SetVehicle(PhysActor);
4756
4757 DoPhysicsPropertyUpdate(UsePhysics, true);
4758
4759 if (!ParentGroup.IsDeleted)
4320 { 4760 {
4321 ParentGroup.CheckSculptAndLoad(); 4761 if (LocalId == ParentGroup.RootPart.LocalId)
4762 {
4763 ParentGroup.CheckSculptAndLoad();
4764 }
4322 } 4765 }
4323 }
4324 4766
4325 if ( 4767 if (
4326 ((AggregateScriptEvents & scriptEvents.collision) != 0) || 4768 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4327 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || 4769 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4328 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || 4770 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4329 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || 4771 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4330 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || 4772 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4331 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || 4773 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4332 (CollisionSound != UUID.Zero) 4774 (CollisionSound != UUID.Zero)
4333 ) 4775 )
4334 { 4776 {
4335 PhysActor.OnCollisionUpdate += PhysicsCollision; 4777 PhysActor.OnCollisionUpdate += PhysicsCollision;
4336 PhysActor.SubscribeEvents(1000); 4778 PhysActor.SubscribeEvents(1000);
4779 }
4337 } 4780 }
4338 } 4781 else // it already has a physical representation
4339 else // it already has a physical representation
4340 {
4341 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4342
4343 if (!ParentGroup.IsDeleted)
4344 { 4782 {
4345 if (LocalId == ParentGroup.RootPart.LocalId) 4783 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4784
4785 if (!ParentGroup.IsDeleted)
4346 { 4786 {
4347 ParentGroup.CheckSculptAndLoad(); 4787 if (LocalId == ParentGroup.RootPart.LocalId)
4788 {
4789 ParentGroup.CheckSculptAndLoad();
4790 }
4348 } 4791 }
4349 } 4792 }
4350 } 4793 }
@@ -4360,7 +4803,7 @@ namespace OpenSim.Region.Framework.Scenes
4360 if (this.PhysActor != null) 4803 if (this.PhysActor != null)
4361 { 4804 {
4362 PhysActor.SetVolumeDetect(1); 4805 PhysActor.SetVolumeDetect(1);
4363 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4806// AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
4364 this.VolumeDetectActive = true; 4807 this.VolumeDetectActive = true;
4365 } 4808 }
4366 } 4809 }
@@ -4368,8 +4811,7 @@ namespace OpenSim.Region.Framework.Scenes
4368 { 4811 {
4369 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4812 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
4370 // (mumbles, well, at least if you have infinte CPU powers :-)) 4813 // (mumbles, well, at least if you have infinte CPU powers :-))
4371 PhysicsActor pa = this.PhysActor; 4814 if (this.PhysActor != null)
4372 if (pa != null)
4373 { 4815 {
4374 PhysActor.SetVolumeDetect(0); 4816 PhysActor.SetVolumeDetect(0);
4375 } 4817 }
@@ -4387,12 +4829,15 @@ namespace OpenSim.Region.Framework.Scenes
4387 } 4829 }
4388 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4830 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4389 4831
4832 // and last in case we have a new actor and not building
4833 if (PhysActor != null && PhysActor.Building != building)
4834 PhysActor.Building = building;
4390 if (ParentGroup != null) 4835 if (ParentGroup != null)
4391 { 4836 {
4392 ParentGroup.HasGroupChanged = true; 4837 ParentGroup.HasGroupChanged = true;
4393 ScheduleFullUpdate(); 4838 ScheduleFullUpdate();
4394 } 4839 }
4395 4840
4396// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4841// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4397 } 4842 }
4398 4843
@@ -4750,5 +5195,17 @@ namespace OpenSim.Region.Framework.Scenes
4750 Color color = Color; 5195 Color color = Color;
4751 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5196 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4752 } 5197 }
5198
5199 public void ResetOwnerChangeFlag()
5200 {
5201 List<UUID> inv = Inventory.GetInventoryList();
5202
5203 foreach (UUID itemID in inv)
5204 {
5205 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5206 item.OwnerChanged = false;
5207 Inventory.UpdateInventoryItem(item, false, false);
5208 }
5209 }
4753 } 5210 }
4754} 5211}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index f2d1915..ca85d10 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
151 foreach (TaskInventoryItem item in items)
152 {
153 item.ParentPartID = m_part.UUID;
154 item.ParentID = m_part.UUID;
155 Items.Add(item.ItemID, item);
156 }
157 } 159 }
160
161 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
162 Items.Clear();
163
164 foreach (TaskInventoryItem item in items)
165 {
166 item.ParentPartID = m_part.UUID;
167 item.ParentID = m_part.UUID;
168 Items.Add(item.ItemID, item);
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)
@@ -255,9 +305,18 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </param> 305 /// </param>
256 public void RemoveScriptInstances(bool sceneObjectBeingDeleted) 306 public void RemoveScriptInstances(bool sceneObjectBeingDeleted)
257 { 307 {
258 List<TaskInventoryItem> scripts = GetInventoryScripts(); 308 Items.LockItemsForRead(true);
259 foreach (TaskInventoryItem item in scripts) 309 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(Items.Values);
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 310 Items.LockItemsForRead(false);
311
312 foreach (TaskInventoryItem item in items)
313 {
314 if ((int)InventoryType.LSL == item.InvType)
315 {
316 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
317 m_part.RemoveScriptEvents(item.ItemID);
318 }
319 }
261 } 320 }
262 321
263 /// <summary> 322 /// <summary>
@@ -271,7 +330,10 @@ namespace OpenSim.Region.Framework.Scenes
271// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 330// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
272 331
273 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 332 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
333 {
334 StoreScriptError(item.ItemID, "no permission");
274 return; 335 return;
336 }
275 337
276 m_part.AddFlag(PrimFlags.Scripted); 338 m_part.AddFlag(PrimFlags.Scripted);
277 339
@@ -280,14 +342,13 @@ namespace OpenSim.Region.Framework.Scenes
280 if (stateSource == 2 && // Prim crossing 342 if (stateSource == 2 && // Prim crossing
281 m_part.ParentGroup.Scene.m_trustBinaries) 343 m_part.ParentGroup.Scene.m_trustBinaries)
282 { 344 {
283 lock (m_items) 345 m_items.LockItemsForWrite(true);
284 { 346 m_items[item.ItemID].PermsMask = 0;
285 m_items[item.ItemID].PermsMask = 0; 347 m_items[item.ItemID].PermsGranter = UUID.Zero;
286 m_items[item.ItemID].PermsGranter = UUID.Zero; 348 m_items.LockItemsForWrite(false);
287 }
288
289 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 349 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
290 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 350 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
351 StoreScriptErrors(item.ItemID, null);
291 m_part.ParentGroup.AddActiveScriptCount(1); 352 m_part.ParentGroup.AddActiveScriptCount(1);
292 m_part.ScheduleFullUpdate(); 353 m_part.ScheduleFullUpdate();
293 return; 354 return;
@@ -296,6 +357,8 @@ namespace OpenSim.Region.Framework.Scenes
296 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 357 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
297 if (null == asset) 358 if (null == asset)
298 { 359 {
360 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
361 StoreScriptError(item.ItemID, msg);
299 m_log.ErrorFormat( 362 m_log.ErrorFormat(
300 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 363 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found",
301 item.Name, item.ItemID, m_part.AbsolutePosition, 364 item.Name, item.ItemID, m_part.AbsolutePosition,
@@ -306,16 +369,21 @@ namespace OpenSim.Region.Framework.Scenes
306 if (m_part.ParentGroup.m_savedScriptState != null) 369 if (m_part.ParentGroup.m_savedScriptState != null)
307 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 370 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
308 371
309 lock (m_items) 372 m_items.LockItemsForWrite(true);
310 {
311 m_items[item.ItemID].OldItemID = item.OldItemID;
312 m_items[item.ItemID].PermsMask = 0;
313 m_items[item.ItemID].PermsGranter = UUID.Zero;
314 }
315 373
374 m_items[item.ItemID].OldItemID = item.OldItemID;
375 m_items[item.ItemID].PermsMask = 0;
376 m_items[item.ItemID].PermsGranter = UUID.Zero;
377
378 m_items.LockItemsForWrite(false);
379
316 string script = Utils.BytesToString(asset.Data); 380 string script = Utils.BytesToString(asset.Data);
317 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 381 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
318 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 382 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
383 StoreScriptErrors(item.ItemID, null);
384 if (!item.ScriptRunning)
385 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
386 m_part.LocalId, item.ItemID);
319 m_part.ParentGroup.AddActiveScriptCount(1); 387 m_part.ParentGroup.AddActiveScriptCount(1);
320 m_part.ScheduleFullUpdate(); 388 m_part.ScheduleFullUpdate();
321 } 389 }
@@ -386,20 +454,146 @@ namespace OpenSim.Region.Framework.Scenes
386 454
387 /// <summary> 455 /// <summary>
388 /// Start a script which is in this prim's inventory. 456 /// Start a script which is in this prim's inventory.
457 /// Some processing may occur in the background, but this routine returns asap.
389 /// </summary> 458 /// </summary>
390 /// <param name="itemId"> 459 /// <param name="itemId">
391 /// A <see cref="UUID"/> 460 /// A <see cref="UUID"/>
392 /// </param> 461 /// </param>
393 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 462 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
394 { 463 {
395 TaskInventoryItem item = GetInventoryItem(itemId); 464 lock (m_scriptErrors)
396 if (item != null) 465 {
397 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 466 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
467 m_scriptErrors.Remove(itemId);
468 }
469 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
470 }
471
472 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
473 {
474 m_items.LockItemsForRead(true);
475 if (m_items.ContainsKey(itemId))
476 {
477 if (m_items.ContainsKey(itemId))
478 {
479 m_items.LockItemsForRead(false);
480 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
481 }
482 else
483 {
484 m_items.LockItemsForRead(false);
485 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
486 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
487 StoreScriptError(itemId, msg);
488 m_log.ErrorFormat(
489 "[PRIM INVENTORY]: " +
490 "Couldn't start script with ID {0} since it {1}", itemId, msg);
491 }
492 }
398 else 493 else
494 {
495 m_items.LockItemsForRead(false);
496 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
497 StoreScriptError(itemId, msg);
399 m_log.ErrorFormat( 498 m_log.ErrorFormat(
400 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", 499 "[PRIM INVENTORY]: Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}",
401 itemId, m_part.Name, m_part.UUID, 500 itemId, m_part.Name, m_part.UUID,
402 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 501 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
502 }
503
504 }
505
506 /// <summary>
507 /// Start a script which is in this prim's inventory and return any compilation error messages.
508 /// </summary>
509 /// <param name="itemId">
510 /// A <see cref="UUID"/>
511 /// </param>
512 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
513 {
514 ArrayList errors;
515
516 // Indicate to CreateScriptInstanceInternal() we want it to
517 // post any compilation/loading error messages
518 lock (m_scriptErrors)
519 {
520 m_scriptErrors[itemId] = null;
521 }
522
523 // Perform compilation/loading
524 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
525
526 // Wait for and retrieve any errors
527 lock (m_scriptErrors)
528 {
529 while ((errors = m_scriptErrors[itemId]) == null)
530 {
531 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
532 {
533 m_log.ErrorFormat(
534 "[PRIM INVENTORY]: " +
535 "timedout waiting for script {0} errors", itemId);
536 errors = m_scriptErrors[itemId];
537 if (errors == null)
538 {
539 errors = new ArrayList(1);
540 errors.Add("timedout waiting for errors");
541 }
542 break;
543 }
544 }
545 m_scriptErrors.Remove(itemId);
546 }
547 return errors;
548 }
549
550 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
551 private void StoreScriptErrors(UUID itemId, ArrayList errors)
552 {
553 lock (m_scriptErrors)
554 {
555 // If compilation/loading initiated via CreateScriptInstance(),
556 // it does not want the errors, so just get out
557 if (!m_scriptErrors.ContainsKey(itemId))
558 {
559 return;
560 }
561
562 // Initiated via CreateScriptInstanceEr(), if we know what the
563 // errors are, save them and wake CreateScriptInstanceEr().
564 if (errors != null)
565 {
566 m_scriptErrors[itemId] = errors;
567 System.Threading.Monitor.PulseAll(m_scriptErrors);
568 return;
569 }
570 }
571
572 // Initiated via CreateScriptInstanceEr() but we don't know what
573 // the errors are yet, so retrieve them from the script engine.
574 // This may involve some waiting internal to GetScriptErrors().
575 errors = GetScriptErrors(itemId);
576
577 // Get a default non-null value to indicate success.
578 if (errors == null)
579 {
580 errors = new ArrayList();
581 }
582
583 // Post to CreateScriptInstanceEr() and wake it up
584 lock (m_scriptErrors)
585 {
586 m_scriptErrors[itemId] = errors;
587 System.Threading.Monitor.PulseAll(m_scriptErrors);
588 }
589 }
590
591 // Like StoreScriptErrors(), but just posts a single string message
592 private void StoreScriptError(UUID itemId, string message)
593 {
594 ArrayList errors = new ArrayList(1);
595 errors.Add(message);
596 StoreScriptErrors(itemId, errors);
403 } 597 }
404 598
405 /// <summary> 599 /// <summary>
@@ -412,15 +606,7 @@ namespace OpenSim.Region.Framework.Scenes
412 /// </param> 606 /// </param>
413 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 607 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
414 { 608 {
415 bool scriptPresent = false; 609 if (m_items.ContainsKey(itemId))
416
417 lock (m_items)
418 {
419 if (m_items.ContainsKey(itemId))
420 scriptPresent = true;
421 }
422
423 if (scriptPresent)
424 { 610 {
425 if (!sceneObjectBeingDeleted) 611 if (!sceneObjectBeingDeleted)
426 m_part.RemoveScriptEvents(itemId); 612 m_part.RemoveScriptEvents(itemId);
@@ -445,14 +631,16 @@ namespace OpenSim.Region.Framework.Scenes
445 /// <returns></returns> 631 /// <returns></returns>
446 private bool InventoryContainsName(string name) 632 private bool InventoryContainsName(string name)
447 { 633 {
448 lock (m_items) 634 m_items.LockItemsForRead(true);
635 foreach (TaskInventoryItem item in m_items.Values)
449 { 636 {
450 foreach (TaskInventoryItem item in m_items.Values) 637 if (item.Name == name)
451 { 638 {
452 if (item.Name == name) 639 m_items.LockItemsForRead(false);
453 return true; 640 return true;
454 } 641 }
455 } 642 }
643 m_items.LockItemsForRead(false);
456 return false; 644 return false;
457 } 645 }
458 646
@@ -494,8 +682,9 @@ namespace OpenSim.Region.Framework.Scenes
494 /// <param name="item"></param> 682 /// <param name="item"></param>
495 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 683 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
496 { 684 {
497 List<TaskInventoryItem> il = GetInventoryItems(); 685 m_items.LockItemsForRead(true);
498 686 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
687 m_items.LockItemsForRead(false);
499 foreach (TaskInventoryItem i in il) 688 foreach (TaskInventoryItem i in il)
500 { 689 {
501 if (i.Name == item.Name) 690 if (i.Name == item.Name)
@@ -533,14 +722,14 @@ namespace OpenSim.Region.Framework.Scenes
533 item.Name = name; 722 item.Name = name;
534 item.GroupID = m_part.GroupID; 723 item.GroupID = m_part.GroupID;
535 724
536 lock (m_items) 725 m_items.LockItemsForWrite(true);
537 m_items.Add(item.ItemID, item); 726 m_items.Add(item.ItemID, item);
538 727 m_items.LockItemsForWrite(false);
539 if (allowedDrop) 728 if (allowedDrop)
540 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 729 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
541 else 730 else
542 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 731 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
543 732
544 m_inventorySerial++; 733 m_inventorySerial++;
545 //m_inventorySerial += 2; 734 //m_inventorySerial += 2;
546 HasInventoryChanged = true; 735 HasInventoryChanged = true;
@@ -556,15 +745,15 @@ namespace OpenSim.Region.Framework.Scenes
556 /// <param name="items"></param> 745 /// <param name="items"></param>
557 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 746 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
558 { 747 {
559 lock (m_items) 748 m_items.LockItemsForWrite(true);
749 foreach (TaskInventoryItem item in items)
560 { 750 {
561 foreach (TaskInventoryItem item in items) 751 m_items.Add(item.ItemID, item);
562 { 752// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
563 m_items.Add(item.ItemID, item);
564// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
565 }
566 m_inventorySerial++;
567 } 753 }
754 m_items.LockItemsForWrite(false);
755
756 m_inventorySerial++;
568 } 757 }
569 758
570 /// <summary> 759 /// <summary>
@@ -575,10 +764,9 @@ namespace OpenSim.Region.Framework.Scenes
575 public TaskInventoryItem GetInventoryItem(UUID itemId) 764 public TaskInventoryItem GetInventoryItem(UUID itemId)
576 { 765 {
577 TaskInventoryItem item; 766 TaskInventoryItem item;
578 767 m_items.LockItemsForRead(true);
579 lock (m_items) 768 m_items.TryGetValue(itemId, out item);
580 m_items.TryGetValue(itemId, out item); 769 m_items.LockItemsForRead(false);
581
582 return item; 770 return item;
583 } 771 }
584 772
@@ -594,15 +782,16 @@ namespace OpenSim.Region.Framework.Scenes
594 { 782 {
595 IList<TaskInventoryItem> items = new List<TaskInventoryItem>(); 783 IList<TaskInventoryItem> items = new List<TaskInventoryItem>();
596 784
597 lock (m_items) 785 m_items.LockItemsForRead(true);
786
787 foreach (TaskInventoryItem item in m_items.Values)
598 { 788 {
599 foreach (TaskInventoryItem item in m_items.Values) 789 if (item.Name == name)
600 { 790 items.Add(item);
601 if (item.Name == name)
602 items.Add(item);
603 }
604 } 791 }
605 792
793 m_items.LockItemsForRead(false);
794
606 return items; 795 return items;
607 } 796 }
608 797
@@ -621,6 +810,9 @@ namespace OpenSim.Region.Framework.Scenes
621 string xmlData = Utils.BytesToString(rezAsset.Data); 810 string xmlData = Utils.BytesToString(rezAsset.Data);
622 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 811 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
623 812
813 group.RootPart.AttachPoint = group.RootPart.Shape.State;
814 group.RootPart.AttachOffset = group.AbsolutePosition;
815
624 group.ResetIDs(); 816 group.ResetIDs();
625 817
626 SceneObjectPart rootPart = group.GetChildPart(group.UUID); 818 SceneObjectPart rootPart = group.GetChildPart(group.UUID);
@@ -695,8 +887,9 @@ namespace OpenSim.Region.Framework.Scenes
695 887
696 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 888 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
697 { 889 {
698 TaskInventoryItem it = GetInventoryItem(item.ItemID); 890 m_items.LockItemsForWrite(true);
699 if (it != null) 891
892 if (m_items.ContainsKey(item.ItemID))
700 { 893 {
701// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 894// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
702 895
@@ -709,14 +902,10 @@ namespace OpenSim.Region.Framework.Scenes
709 item.GroupID = m_part.GroupID; 902 item.GroupID = m_part.GroupID;
710 903
711 if (item.AssetID == UUID.Zero) 904 if (item.AssetID == UUID.Zero)
712 item.AssetID = it.AssetID; 905 item.AssetID = m_items[item.ItemID].AssetID;
713 906
714 lock (m_items) 907 m_items[item.ItemID] = item;
715 { 908 m_inventorySerial++;
716 m_items[item.ItemID] = item;
717 m_inventorySerial++;
718 }
719
720 if (fireScriptEvents) 909 if (fireScriptEvents)
721 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 910 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
722 911
@@ -725,7 +914,7 @@ namespace OpenSim.Region.Framework.Scenes
725 HasInventoryChanged = true; 914 HasInventoryChanged = true;
726 m_part.ParentGroup.HasGroupChanged = true; 915 m_part.ParentGroup.HasGroupChanged = true;
727 } 916 }
728 917 m_items.LockItemsForWrite(false);
729 return true; 918 return true;
730 } 919 }
731 else 920 else
@@ -736,8 +925,9 @@ namespace OpenSim.Region.Framework.Scenes
736 item.ItemID, m_part.Name, m_part.UUID, 925 item.ItemID, m_part.Name, m_part.UUID,
737 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 926 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
738 } 927 }
739 return false; 928 m_items.LockItemsForWrite(false);
740 929
930 return false;
741 } 931 }
742 932
743 /// <summary> 933 /// <summary>
@@ -748,43 +938,59 @@ namespace OpenSim.Region.Framework.Scenes
748 /// in this prim's inventory.</returns> 938 /// in this prim's inventory.</returns>
749 public int RemoveInventoryItem(UUID itemID) 939 public int RemoveInventoryItem(UUID itemID)
750 { 940 {
751 TaskInventoryItem item = GetInventoryItem(itemID); 941 m_items.LockItemsForRead(true);
752 if (item != null) 942
943 if (m_items.ContainsKey(itemID))
753 { 944 {
754 int type = m_items[itemID].InvType; 945 int type = m_items[itemID].InvType;
946 m_items.LockItemsForRead(false);
755 if (type == 10) // Script 947 if (type == 10) // Script
756 { 948 {
757 m_part.RemoveScriptEvents(itemID);
758 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 949 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
759 } 950 }
951 m_items.LockItemsForWrite(true);
760 m_items.Remove(itemID); 952 m_items.Remove(itemID);
953 m_items.LockItemsForWrite(false);
761 m_inventorySerial++; 954 m_inventorySerial++;
762 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 955 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
763 956
764 HasInventoryChanged = true; 957 HasInventoryChanged = true;
765 m_part.ParentGroup.HasGroupChanged = true; 958 m_part.ParentGroup.HasGroupChanged = true;
766 959
767 if (!ContainsScripts()) 960 int scriptcount = 0;
961 m_items.LockItemsForRead(true);
962 foreach (TaskInventoryItem item in m_items.Values)
963 {
964 if (item.Type == 10)
965 {
966 scriptcount++;
967 }
968 }
969 m_items.LockItemsForRead(false);
970
971
972 if (scriptcount <= 0)
973 {
768 m_part.RemFlag(PrimFlags.Scripted); 974 m_part.RemFlag(PrimFlags.Scripted);
975 }
769 976
770 m_part.ScheduleFullUpdate(); 977 m_part.ScheduleFullUpdate();
771 978
772 return type; 979 return type;
773
774 } 980 }
775 else 981 else
776 { 982 {
983 m_items.LockItemsForRead(false);
777 m_log.ErrorFormat( 984 m_log.ErrorFormat(
778 "[PRIM INVENTORY]: " + 985 "[PRIM INVENTORY]: " +
779 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 986 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
780 itemID, m_part.Name, m_part.UUID, 987 itemID, m_part.Name, m_part.UUID);
781 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
782 } 988 }
783 989
784 return -1; 990 return -1;
785 } 991 }
786 992
787 private bool CreateInventoryFile() 993 private bool CreateInventoryFileName()
788 { 994 {
789// m_log.DebugFormat( 995// m_log.DebugFormat(
790// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 996// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -793,116 +999,125 @@ namespace OpenSim.Region.Framework.Scenes
793 if (m_inventoryFileName == String.Empty || 999 if (m_inventoryFileName == String.Empty ||
794 m_inventoryFileNameSerial < m_inventorySerial) 1000 m_inventoryFileNameSerial < m_inventorySerial)
795 { 1001 {
796 // Something changed, we need to create a new file
797 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 1002 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
798 m_inventoryFileNameSerial = m_inventorySerial; 1003 m_inventoryFileNameSerial = m_inventorySerial;
799 1004
800 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1005 return true;
1006 }
1007
1008 return false;
1009 }
1010
1011 /// <summary>
1012 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1013 /// </summary>
1014 /// <param name="xferManager"></param>
1015 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1016 {
1017 bool changed = CreateInventoryFileName();
1018
1019 bool includeAssets = false;
1020 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1021 includeAssets = true;
1022
1023 if (m_inventoryPrivileged != includeAssets)
1024 changed = true;
1025
1026 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
1027
1028 Items.LockItemsForRead(true);
1029
1030 if (m_inventorySerial == 0) // No inventory
1031 {
1032 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1033 Items.LockItemsForRead(false);
1034 return;
1035 }
801 1036
802 lock (m_items) 1037 if (m_items.Count == 0) // No inventory
1038 {
1039 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1040 Items.LockItemsForRead(false);
1041 return;
1042 }
1043
1044 if (!changed)
1045 {
1046 if (m_inventoryFileData.Length > 2)
803 { 1047 {
804 foreach (TaskInventoryItem item in m_items.Values) 1048 xferManager.AddNewFile(m_inventoryFileName,
805 { 1049 m_inventoryFileData);
806// m_log.DebugFormat( 1050 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
807// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1051 Util.StringToBytes256(m_inventoryFileName));
808// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
809 1052
810 UUID ownerID = item.OwnerID; 1053 Items.LockItemsForRead(false);
811 uint everyoneMask = 0; 1054 return;
812 uint baseMask = item.BasePermissions; 1055 }
813 uint ownerMask = item.CurrentPermissions; 1056 }
814 uint groupMask = item.GroupPermissions;
815 1057
816 invString.AddItemStart(); 1058 m_inventoryPrivileged = includeAssets;
817 invString.AddNameValueLine("item_id", item.ItemID.ToString());
818 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
819 1059
820 invString.AddPermissionsStart(); 1060 foreach (TaskInventoryItem item in m_items.Values)
1061 {
1062 UUID ownerID = item.OwnerID;
1063 uint everyoneMask = 0;
1064 uint baseMask = item.BasePermissions;
1065 uint ownerMask = item.CurrentPermissions;
1066 uint groupMask = item.GroupPermissions;
821 1067
822 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1068 invString.AddItemStart();
823 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1069 invString.AddNameValueLine("item_id", item.ItemID.ToString());
824 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1070 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
825 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
826 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
827 1071
828 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1072 invString.AddPermissionsStart();
829 invString.AddNameValueLine("owner_id", ownerID.ToString());
830 1073
831 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1074 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1075 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1076 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1077 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1078 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
832 1079
833 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1080 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
834 invString.AddSectionEnd(); 1081 invString.AddNameValueLine("owner_id", ownerID.ToString());
835 1082
836 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1083 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
837 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
838 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
839 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
840 1084
841 invString.AddSaleStart(); 1085 invString.AddNameValueLine("group_id", item.GroupID.ToString());
842 invString.AddNameValueLine("sale_type", "not"); 1086 invString.AddSectionEnd();
843 invString.AddNameValueLine("sale_price", "0");
844 invString.AddSectionEnd();
845 1087
846 invString.AddNameValueLine("name", item.Name + "|"); 1088 if (includeAssets)
847 invString.AddNameValueLine("desc", item.Description + "|"); 1089 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1090 else
1091 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1092 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1093 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1094 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
848 1095
849 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1096 invString.AddSaleStart();
850 invString.AddSectionEnd(); 1097 invString.AddNameValueLine("sale_type", "not");
851 } 1098 invString.AddNameValueLine("sale_price", "0");
852 } 1099 invString.AddSectionEnd();
853 1100
854 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1101 invString.AddNameValueLine("name", item.Name + "|");
1102 invString.AddNameValueLine("desc", item.Description + "|");
855 1103
856 return true; 1104 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1105 invString.AddSectionEnd();
857 } 1106 }
858 1107
859 // No need to recreate, the existing file is fine 1108 Items.LockItemsForRead(false);
860 return false;
861 }
862
863 /// <summary>
864 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
865 /// </summary>
866 /// <param name="xferManager"></param>
867 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
868 {
869 lock (m_items)
870 {
871 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
872 // a new script if any previous deletion has left the prim inventory empty.
873 if (m_items.Count == 0) // No inventory
874 {
875// m_log.DebugFormat(
876// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
877// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
878 1109
879 client.SendTaskInventory(m_part.UUID, 0, new byte[0]); 1110 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
880 return;
881 }
882 1111
883 CreateInventoryFile(); 1112 if (m_inventoryFileData.Length > 2)
884 1113 {
885 // In principle, we should only do the rest if the inventory changed; 1114 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
886 // by sending m_inventorySerial to the client, it ought to know 1115 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
887 // that nothing changed and that it doesn't need to request the file. 1116 Util.StringToBytes256(m_inventoryFileName));
888 // Unfortunately, it doesn't look like the client optimizes this; 1117 return;
889 // the client seems to always come back and request the Xfer,
890 // no matter what value m_inventorySerial has.
891 // FIXME: Could probably be > 0 here rather than > 2
892 if (m_inventoryFileData.Length > 2)
893 {
894 // Add the file for Xfer
895 // m_log.DebugFormat(
896 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
897 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
898
899 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
900 }
901
902 // Tell the client we're ready to Xfer the file
903 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
904 Util.StringToBytes256(m_inventoryFileName));
905 } 1118 }
1119
1120 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
906 } 1121 }
907 1122
908 /// <summary> 1123 /// <summary>
@@ -911,13 +1126,19 @@ namespace OpenSim.Region.Framework.Scenes
911 /// <param name="datastore"></param> 1126 /// <param name="datastore"></param>
912 public void ProcessInventoryBackup(ISimulationDataService datastore) 1127 public void ProcessInventoryBackup(ISimulationDataService datastore)
913 { 1128 {
914 if (HasInventoryChanged) 1129// Removed this because linking will cause an immediate delete of the new
915 { 1130// child prim from the database and the subsequent storing of the prim sees
916 HasInventoryChanged = false; 1131// the inventory of it as unchanged and doesn't store it at all. The overhead
917 List<TaskInventoryItem> items = GetInventoryItems(); 1132// of storing prim inventory needlessly is much less than the aggravation
918 datastore.StorePrimInventory(m_part.UUID, items); 1133// of prim inventory loss.
1134// if (HasInventoryChanged)
1135// {
1136 Items.LockItemsForRead(true);
1137 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1138 Items.LockItemsForRead(false);
919 1139
920 } 1140 HasInventoryChanged = false;
1141// }
921 } 1142 }
922 1143
923 public class InventoryStringBuilder 1144 public class InventoryStringBuilder
@@ -983,82 +1204,63 @@ namespace OpenSim.Region.Framework.Scenes
983 { 1204 {
984 uint mask=0x7fffffff; 1205 uint mask=0x7fffffff;
985 1206
986 lock (m_items) 1207 foreach (TaskInventoryItem item in m_items.Values)
987 { 1208 {
988 foreach (TaskInventoryItem item in m_items.Values) 1209 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1210 mask &= ~((uint)PermissionMask.Copy >> 13);
1211 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1212 mask &= ~((uint)PermissionMask.Transfer >> 13);
1213 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1214 mask &= ~((uint)PermissionMask.Modify >> 13);
1215
1216 if (item.InvType == (int)InventoryType.Object)
989 { 1217 {
990 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1218 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
991 mask &= ~((uint)PermissionMask.Copy >> 13); 1219 mask &= ~((uint)PermissionMask.Copy >> 13);
992 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1220 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
993 mask &= ~((uint)PermissionMask.Transfer >> 13); 1221 mask &= ~((uint)PermissionMask.Transfer >> 13);
994 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1222 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
995 mask &= ~((uint)PermissionMask.Modify >> 13); 1223 mask &= ~((uint)PermissionMask.Modify >> 13);
996
997 if (item.InvType != (int)InventoryType.Object)
998 {
999 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1000 mask &= ~((uint)PermissionMask.Copy >> 13);
1001 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1002 mask &= ~((uint)PermissionMask.Transfer >> 13);
1003 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1004 mask &= ~((uint)PermissionMask.Modify >> 13);
1005 }
1006 else
1007 {
1008 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1009 mask &= ~((uint)PermissionMask.Copy >> 13);
1010 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1011 mask &= ~((uint)PermissionMask.Transfer >> 13);
1012 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1013 mask &= ~((uint)PermissionMask.Modify >> 13);
1014 }
1015
1016 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1017 mask &= ~(uint)PermissionMask.Copy;
1018 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1019 mask &= ~(uint)PermissionMask.Transfer;
1020 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1021 mask &= ~(uint)PermissionMask.Modify;
1022 } 1224 }
1225
1226 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1227 mask &= ~(uint)PermissionMask.Copy;
1228 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1229 mask &= ~(uint)PermissionMask.Transfer;
1230 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1231 mask &= ~(uint)PermissionMask.Modify;
1023 } 1232 }
1024
1025 return mask; 1233 return mask;
1026 } 1234 }
1027 1235
1028 public void ApplyNextOwnerPermissions() 1236 public void ApplyNextOwnerPermissions()
1029 { 1237 {
1030 lock (m_items) 1238 foreach (TaskInventoryItem item in m_items.Values)
1031 { 1239 {
1032 foreach (TaskInventoryItem item in m_items.Values) 1240 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1033 { 1241 {
1034 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1242 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1035 { 1243 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1036 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) 1244 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1037 item.CurrentPermissions &= ~(uint)PermissionMask.Copy; 1245 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1038 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) 1246 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1039 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; 1247 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1040 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1041 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1042 }
1043 item.CurrentPermissions &= item.NextPermissions;
1044 item.BasePermissions &= item.NextPermissions;
1045 item.EveryonePermissions &= item.NextPermissions;
1046 item.OwnerChanged = true;
1047 item.PermsMask = 0;
1048 item.PermsGranter = UUID.Zero;
1049 } 1248 }
1249 item.OwnerChanged = true;
1250 item.CurrentPermissions &= item.NextPermissions;
1251 item.BasePermissions &= item.NextPermissions;
1252 item.EveryonePermissions &= item.NextPermissions;
1253 item.PermsMask = 0;
1254 item.PermsGranter = UUID.Zero;
1050 } 1255 }
1051 } 1256 }
1052 1257
1053 public void ApplyGodPermissions(uint perms) 1258 public void ApplyGodPermissions(uint perms)
1054 { 1259 {
1055 lock (m_items) 1260 foreach (TaskInventoryItem item in m_items.Values)
1056 { 1261 {
1057 foreach (TaskInventoryItem item in m_items.Values) 1262 item.CurrentPermissions = perms;
1058 { 1263 item.BasePermissions = perms;
1059 item.CurrentPermissions = perms;
1060 item.BasePermissions = perms;
1061 }
1062 } 1264 }
1063 1265
1064 m_inventorySerial++; 1266 m_inventorySerial++;
@@ -1071,17 +1273,13 @@ namespace OpenSim.Region.Framework.Scenes
1071 /// <returns></returns> 1273 /// <returns></returns>
1072 public bool ContainsScripts() 1274 public bool ContainsScripts()
1073 { 1275 {
1074 lock (m_items) 1276 foreach (TaskInventoryItem item in m_items.Values)
1075 { 1277 {
1076 foreach (TaskInventoryItem item in m_items.Values) 1278 if (item.InvType == (int)InventoryType.LSL)
1077 { 1279 {
1078 if (item.InvType == (int)InventoryType.LSL) 1280 return true;
1079 {
1080 return true;
1081 }
1082 } 1281 }
1083 } 1282 }
1084
1085 return false; 1283 return false;
1086 } 1284 }
1087 1285
@@ -1089,11 +1287,8 @@ namespace OpenSim.Region.Framework.Scenes
1089 { 1287 {
1090 List<UUID> ret = new List<UUID>(); 1288 List<UUID> ret = new List<UUID>();
1091 1289
1092 lock (m_items) 1290 foreach (TaskInventoryItem item in m_items.Values)
1093 { 1291 ret.Add(item.ItemID);
1094 foreach (TaskInventoryItem item in m_items.Values)
1095 ret.Add(item.ItemID);
1096 }
1097 1292
1098 return ret; 1293 return ret;
1099 } 1294 }
@@ -1124,6 +1319,11 @@ namespace OpenSim.Region.Framework.Scenes
1124 1319
1125 public Dictionary<UUID, string> GetScriptStates() 1320 public Dictionary<UUID, string> GetScriptStates()
1126 { 1321 {
1322 return GetScriptStates(false);
1323 }
1324
1325 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1326 {
1127 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1327 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1128 1328
1129 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1329 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1134,25 +1334,35 @@ namespace OpenSim.Region.Framework.Scenes
1134 if (engines.Length == 0) // No engine at all 1334 if (engines.Length == 0) // No engine at all
1135 return ret; 1335 return ret;
1136 1336
1137 List<TaskInventoryItem> scripts = GetInventoryScripts(); 1337 Items.LockItemsForRead(true);
1138 1338 foreach (TaskInventoryItem item in m_items.Values)
1139 foreach (TaskInventoryItem item in scripts)
1140 { 1339 {
1141 foreach (IScriptModule e in engines) 1340 if (item.InvType == (int)InventoryType.LSL)
1142 { 1341 {
1143 if (e != null) 1342 foreach (IScriptModule e in engines)
1144 { 1343 {
1145 string n = e.GetXMLState(item.ItemID); 1344 if (e != null)
1146 if (n != String.Empty)
1147 { 1345 {
1148 if (!ret.ContainsKey(item.ItemID)) 1346 string n = e.GetXMLState(item.ItemID);
1149 ret[item.ItemID] = n; 1347 if (n != String.Empty)
1150 break; 1348 {
1349 if (oldIDs)
1350 {
1351 if (!ret.ContainsKey(item.OldItemID))
1352 ret[item.OldItemID] = n;
1353 }
1354 else
1355 {
1356 if (!ret.ContainsKey(item.ItemID))
1357 ret[item.ItemID] = n;
1358 }
1359 break;
1360 }
1151 } 1361 }
1152 } 1362 }
1153 } 1363 }
1154 } 1364 }
1155 1365 Items.LockItemsForRead(false);
1156 return ret; 1366 return ret;
1157 } 1367 }
1158 1368
@@ -1162,21 +1372,27 @@ namespace OpenSim.Region.Framework.Scenes
1162 if (engines.Length == 0) 1372 if (engines.Length == 0)
1163 return; 1373 return;
1164 1374
1165 List<TaskInventoryItem> scripts = GetInventoryScripts();
1166 1375
1167 foreach (TaskInventoryItem item in scripts) 1376 Items.LockItemsForRead(true);
1377
1378 foreach (TaskInventoryItem item in m_items.Values)
1168 { 1379 {
1169 foreach (IScriptModule engine in engines) 1380 if (item.InvType == (int)InventoryType.LSL)
1170 { 1381 {
1171 if (engine != null) 1382 foreach (IScriptModule engine in engines)
1172 { 1383 {
1173 if (item.OwnerChanged) 1384 if (engine != null)
1174 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER }); 1385 {
1175 item.OwnerChanged = false; 1386 if (item.OwnerChanged)
1176 engine.ResumeScript(item.ItemID); 1387 engine.PostScriptEvent(item.ItemID, "changed", new Object[] { (int)Changed.OWNER });
1388 item.OwnerChanged = false;
1389 engine.ResumeScript(item.ItemID);
1390 }
1177 } 1391 }
1178 } 1392 }
1179 } 1393 }
1394
1395 Items.LockItemsForRead(false);
1180 } 1396 }
1181 } 1397 }
1182} 1398}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cf60c69..2346c60 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -91,7 +91,7 @@ namespace OpenSim.Region.Framework.Scenes
91 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 91 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
92 /// issue #1716 92 /// issue #1716
93 /// </summary> 93 /// </summary>
94 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); 94 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
95 95
96 /// <summary> 96 /// <summary>
97 /// Movement updates for agents in neighboring regions are sent directly to clients. 97 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -168,6 +168,7 @@ namespace OpenSim.Region.Framework.Scenes
168// private int m_lastColCount = -1; //KF: Look for Collision chnages 168// private int m_lastColCount = -1; //KF: Look for Collision chnages
169// private int m_updateCount = 0; //KF: Update Anims for a while 169// private int m_updateCount = 0; //KF: Update Anims for a while
170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 170// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
171 private List<uint> m_lastColliders = new List<uint>();
171 172
172 private TeleportFlags m_teleportFlags; 173 private TeleportFlags m_teleportFlags;
173 public TeleportFlags TeleportFlags 174 public TeleportFlags TeleportFlags
@@ -229,6 +230,11 @@ namespace OpenSim.Region.Framework.Scenes
229 //private int m_moveToPositionStateStatus; 230 //private int m_moveToPositionStateStatus;
230 //***************************************************** 231 //*****************************************************
231 232
233 private bool m_collisionEventFlag = false;
234 private object m_collisionEventLock = new Object();
235
236 private Vector3 m_prevSitOffset;
237
232 protected AvatarAppearance m_appearance; 238 protected AvatarAppearance m_appearance;
233 239
234 public AvatarAppearance Appearance 240 public AvatarAppearance Appearance
@@ -568,6 +574,13 @@ namespace OpenSim.Region.Framework.Scenes
568 /// </summary> 574 /// </summary>
569 public uint ParentID { get; set; } 575 public uint ParentID { get; set; }
570 576
577 public UUID ParentUUID
578 {
579 get { return m_parentUUID; }
580 set { m_parentUUID = value; }
581 }
582 private UUID m_parentUUID = UUID.Zero;
583
571 /// <summary> 584 /// <summary>
572 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null. 585 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
573 /// </summary> 586 /// </summary>
@@ -797,10 +810,38 @@ namespace OpenSim.Region.Framework.Scenes
797 "[SCENE]: Upgrading child to root agent for {0} in {1}", 810 "[SCENE]: Upgrading child to root agent for {0} in {1}",
798 Name, m_scene.RegionInfo.RegionName); 811 Name, m_scene.RegionInfo.RegionName);
799 812
800 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
801
802 bool wasChild = IsChildAgent; 813 bool wasChild = IsChildAgent;
803 IsChildAgent = false; 814
815 if (ParentUUID != UUID.Zero)
816 {
817 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
818 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
819 if (part == null)
820 {
821 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
822 }
823 else
824 {
825 part.ParentGroup.AddAvatar(UUID);
826 if (part.SitTargetPosition != Vector3.Zero)
827 part.SitTargetAvatar = UUID;
828 ParentPosition = part.GetWorldPosition();
829 ParentID = part.LocalId;
830 ParentPart = part;
831 m_pos = m_prevSitOffset;
832 pos = ParentPosition;
833 }
834 ParentUUID = UUID.Zero;
835
836 IsChildAgent = false;
837
838 Animator.TrySetMovementAnimation("SIT");
839 }
840 else
841 {
842 IsChildAgent = false;
843 }
844
804 845
805 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 846 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
806 if (gm != null) 847 if (gm != null)
@@ -810,62 +851,64 @@ namespace OpenSim.Region.Framework.Scenes
810 851
811 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 852 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
812 853
813 // Moved this from SendInitialData to ensure that Appearance is initialized 854 if (ParentID == 0)
814 // before the inventory is processed in MakeRootAgent. This fixes a race condition
815 // related to the handling of attachments
816 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
817 if (m_scene.TestBorderCross(pos, Cardinals.E))
818 { 855 {
819 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 856 // Moved this from SendInitialData to ensure that Appearance is initialized
820 pos.X = crossedBorder.BorderLine.Z - 1; 857 // before the inventory is processed in MakeRootAgent. This fixes a race condition
821 } 858 // related to the handling of attachments
859 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
860 if (m_scene.TestBorderCross(pos, Cardinals.E))
861 {
862 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
863 pos.X = crossedBorder.BorderLine.Z - 1;
864 }
822 865
823 if (m_scene.TestBorderCross(pos, Cardinals.N)) 866 if (m_scene.TestBorderCross(pos, Cardinals.N))
824 { 867 {
825 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 868 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
826 pos.Y = crossedBorder.BorderLine.Z - 1; 869 pos.Y = crossedBorder.BorderLine.Z - 1;
827 } 870 }
828 871
829 CheckAndAdjustLandingPoint(ref pos); 872 CheckAndAdjustLandingPoint(ref pos);
830 873
831 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 874 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
832 { 875 {
833 m_log.WarnFormat( 876 m_log.WarnFormat(
834 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 877 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
835 pos, Name, UUID); 878 pos, Name, UUID);
836 879
837 if (pos.X < 0f) pos.X = 0f; 880 if (pos.X < 0f) pos.X = 0f;
838 if (pos.Y < 0f) pos.Y = 0f; 881 if (pos.Y < 0f) pos.Y = 0f;
839 if (pos.Z < 0f) pos.Z = 0f; 882 if (pos.Z < 0f) pos.Z = 0f;
840 } 883 }
841 884
842 float localAVHeight = 1.56f; 885 float localAVHeight = 1.56f;
843 if (Appearance.AvatarHeight > 0) 886 if (Appearance.AvatarHeight > 0)
844 localAVHeight = Appearance.AvatarHeight; 887 localAVHeight = Appearance.AvatarHeight;
845 888
846 float posZLimit = 0; 889 float posZLimit = 0;
847 890
848 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 891 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
849 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 892 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
850 893
851 float newPosZ = posZLimit + localAVHeight / 2; 894 float newPosZ = posZLimit + localAVHeight / 2;
852 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 895 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
853 { 896 {
854 pos.Z = newPosZ; 897 pos.Z = newPosZ;
855 } 898 }
856 AbsolutePosition = pos; 899 AbsolutePosition = pos;
857 900
858 AddToPhysicalScene(isFlying); 901 AddToPhysicalScene(isFlying);
859 902
860 if (ForceFly) 903 if (ForceFly)
861 { 904 {
862 Flying = true; 905 Flying = true;
863 } 906 }
864 else if (FlyDisabled) 907 else if (FlyDisabled)
865 { 908 {
866 Flying = false; 909 Flying = false;
910 }
867 } 911 }
868
869 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 912 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
870 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 913 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
871 // elsewhere anyway 914 // elsewhere anyway
@@ -883,14 +926,19 @@ namespace OpenSim.Region.Framework.Scenes
883 { 926 {
884 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 927 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
885 // Resume scripts 928 // Resume scripts
886 foreach (SceneObjectGroup sog in m_attachments) 929 Util.FireAndForget(delegate(object x) {
887 { 930 foreach (SceneObjectGroup sog in m_attachments)
888 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 931 {
889 sog.ResumeScripts(); 932 sog.ScheduleGroupForFullUpdate();
890 } 933 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
934 sog.ResumeScripts();
935 }
936 });
891 } 937 }
892 } 938 }
893 939
940 SendAvatarDataToAllAgents();
941
894 // send the animations of the other presences to me 942 // send the animations of the other presences to me
895 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) 943 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
896 { 944 {
@@ -1687,9 +1735,9 @@ namespace OpenSim.Region.Framework.Scenes
1687 if (pos.Z - terrainHeight < 0.2) 1735 if (pos.Z - terrainHeight < 0.2)
1688 pos.Z = terrainHeight; 1736 pos.Z = terrainHeight;
1689 1737
1690 m_log.DebugFormat( 1738// m_log.DebugFormat(
1691 "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 1739// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
1692 Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 1740// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
1693 1741
1694 if (noFly) 1742 if (noFly)
1695 Flying = false; 1743 Flying = false;
@@ -1746,8 +1794,11 @@ namespace OpenSim.Region.Framework.Scenes
1746// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 1794// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
1747 1795
1748 SitGround = false; 1796 SitGround = false;
1797
1798/* move this down so avatar gets physical in the new position and not where it is siting
1749 if (PhysicsActor == null) 1799 if (PhysicsActor == null)
1750 AddToPhysicalScene(false); 1800 AddToPhysicalScene(false);
1801 */
1751 1802
1752 if (ParentID != 0) 1803 if (ParentID != 0)
1753 { 1804 {
@@ -1771,6 +1822,7 @@ namespace OpenSim.Region.Framework.Scenes
1771 if (part.SitTargetAvatar == UUID) 1822 if (part.SitTargetAvatar == UUID)
1772 part.SitTargetAvatar = UUID.Zero; 1823 part.SitTargetAvatar = UUID.Zero;
1773 1824
1825 part.ParentGroup.DeleteAvatar(UUID);
1774 ParentPosition = part.GetWorldPosition(); 1826 ParentPosition = part.GetWorldPosition();
1775 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1827 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1776 1828
@@ -1779,6 +1831,10 @@ namespace OpenSim.Region.Framework.Scenes
1779 1831
1780 ParentID = 0; 1832 ParentID = 0;
1781 ParentPart = null; 1833 ParentPart = null;
1834
1835 if (PhysicsActor == null)
1836 AddToPhysicalScene(false);
1837
1782 SendAvatarDataToAllAgents(); 1838 SendAvatarDataToAllAgents();
1783 m_requestedSitTargetID = 0; 1839 m_requestedSitTargetID = 0;
1784 1840
@@ -1786,6 +1842,9 @@ namespace OpenSim.Region.Framework.Scenes
1786 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 1842 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1787 } 1843 }
1788 1844
1845 else if (PhysicsActor == null)
1846 AddToPhysicalScene(false);
1847
1789 Animator.TrySetMovementAnimation("STAND"); 1848 Animator.TrySetMovementAnimation("STAND");
1790 } 1849 }
1791 1850
@@ -1909,7 +1968,7 @@ namespace OpenSim.Region.Framework.Scenes
1909 forceMouselook = part.GetForceMouselook(); 1968 forceMouselook = part.GetForceMouselook();
1910 1969
1911 ControllingClient.SendSitResponse( 1970 ControllingClient.SendSitResponse(
1912 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 1971 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1913 1972
1914 m_requestedSitTargetUUID = targetID; 1973 m_requestedSitTargetUUID = targetID;
1915 1974
@@ -2191,14 +2250,36 @@ namespace OpenSim.Region.Framework.Scenes
2191 2250
2192 //Quaternion result = (sitTargetOrient * vq) * nq; 2251 //Quaternion result = (sitTargetOrient * vq) * nq;
2193 2252
2194 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2253 double x, y, z, m;
2254
2255 Quaternion r = sitTargetOrient;
2256 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2257
2258 if (Math.Abs(1.0 - m) > 0.000001)
2259 {
2260 m = 1.0 / Math.Sqrt(m);
2261 r.X *= (float)m;
2262 r.Y *= (float)m;
2263 r.Z *= (float)m;
2264 r.W *= (float)m;
2265 }
2266
2267 x = 2 * (r.X * r.Z + r.Y * r.W);
2268 y = 2 * (-r.X * r.W + r.Y * r.Z);
2269 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2270
2271 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2272 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2273 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2195 Rotation = sitTargetOrient; 2274 Rotation = sitTargetOrient;
2196 ParentPosition = part.AbsolutePosition; 2275 ParentPosition = part.AbsolutePosition;
2276 part.ParentGroup.AddAvatar(UUID);
2197 } 2277 }
2198 else 2278 else
2199 { 2279 {
2200 m_pos -= part.AbsolutePosition; 2280 m_pos -= part.AbsolutePosition;
2201 ParentPosition = part.AbsolutePosition; 2281 ParentPosition = part.AbsolutePosition;
2282 part.ParentGroup.AddAvatar(UUID);
2202 2283
2203// m_log.DebugFormat( 2284// m_log.DebugFormat(
2204// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2285// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -3037,6 +3118,9 @@ namespace OpenSim.Region.Framework.Scenes
3037 cAgent.AlwaysRun = SetAlwaysRun; 3118 cAgent.AlwaysRun = SetAlwaysRun;
3038 3119
3039 cAgent.Appearance = new AvatarAppearance(Appearance); 3120 cAgent.Appearance = new AvatarAppearance(Appearance);
3121
3122 cAgent.ParentPart = ParentUUID;
3123 cAgent.SitOffset = m_pos;
3040 3124
3041 lock (scriptedcontrols) 3125 lock (scriptedcontrols)
3042 { 3126 {
@@ -3096,6 +3180,8 @@ namespace OpenSim.Region.Framework.Scenes
3096 CameraAtAxis = cAgent.AtAxis; 3180 CameraAtAxis = cAgent.AtAxis;
3097 CameraLeftAxis = cAgent.LeftAxis; 3181 CameraLeftAxis = cAgent.LeftAxis;
3098 CameraUpAxis = cAgent.UpAxis; 3182 CameraUpAxis = cAgent.UpAxis;
3183 ParentUUID = cAgent.ParentPart;
3184 m_prevSitOffset = cAgent.SitOffset;
3099 3185
3100 // When we get to the point of re-computing neighbors everytime this 3186 // When we get to the point of re-computing neighbors everytime this
3101 // changes, then start using the agent's drawdistance rather than the 3187 // changes, then start using the agent's drawdistance rather than the
@@ -3302,6 +3388,8 @@ namespace OpenSim.Region.Framework.Scenes
3302 } 3388 }
3303 } 3389 }
3304 3390
3391 RaiseCollisionScriptEvents(coldata);
3392
3305 if (Invulnerable) 3393 if (Invulnerable)
3306 return; 3394 return;
3307 3395
@@ -3813,6 +3901,12 @@ namespace OpenSim.Region.Framework.Scenes
3813 3901
3814 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 3902 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3815 { 3903 {
3904 string reason;
3905
3906 // Honor bans
3907 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
3908 return;
3909
3816 SceneObjectGroup telehub = null; 3910 SceneObjectGroup telehub = null;
3817 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 3911 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
3818 { 3912 {
@@ -3852,11 +3946,173 @@ namespace OpenSim.Region.Framework.Scenes
3852 pos = land.LandData.UserLocation; 3946 pos = land.LandData.UserLocation;
3853 } 3947 }
3854 } 3948 }
3855 3949
3856 land.SendLandUpdateToClient(ControllingClient); 3950 land.SendLandUpdateToClient(ControllingClient);
3857 } 3951 }
3858 } 3952 }
3859 3953
3954 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
3955 {
3956 lock(m_collisionEventLock)
3957 {
3958 if (m_collisionEventFlag)
3959 return;
3960 m_collisionEventFlag = true;
3961 }
3962
3963 Util.FireAndForget(delegate(object x)
3964 {
3965 try
3966 {
3967 List<uint> thisHitColliders = new List<uint>();
3968 List<uint> endedColliders = new List<uint>();
3969 List<uint> startedColliders = new List<uint>();
3970
3971 foreach (uint localid in coldata.Keys)
3972 {
3973 thisHitColliders.Add(localid);
3974 if (!m_lastColliders.Contains(localid))
3975 {
3976 startedColliders.Add(localid);
3977 }
3978 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3979 }
3980
3981 // calculate things that ended colliding
3982 foreach (uint localID in m_lastColliders)
3983 {
3984 if (!thisHitColliders.Contains(localID))
3985 {
3986 endedColliders.Add(localID);
3987 }
3988 }
3989 //add the items that started colliding this time to the last colliders list.
3990 foreach (uint localID in startedColliders)
3991 {
3992 m_lastColliders.Add(localID);
3993 }
3994 // remove things that ended colliding from the last colliders list
3995 foreach (uint localID in endedColliders)
3996 {
3997 m_lastColliders.Remove(localID);
3998 }
3999
4000 // do event notification
4001 if (startedColliders.Count > 0)
4002 {
4003 ColliderArgs StartCollidingMessage = new ColliderArgs();
4004 List<DetectedObject> colliding = new List<DetectedObject>();
4005 foreach (uint localId in startedColliders)
4006 {
4007 if (localId == 0)
4008 continue;
4009
4010 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4011 string data = "";
4012 if (obj != null)
4013 {
4014 DetectedObject detobj = new DetectedObject();
4015 detobj.keyUUID = obj.UUID;
4016 detobj.nameStr = obj.Name;
4017 detobj.ownerUUID = obj.OwnerID;
4018 detobj.posVector = obj.AbsolutePosition;
4019 detobj.rotQuat = obj.GetWorldRotation();
4020 detobj.velVector = obj.Velocity;
4021 detobj.colliderType = 0;
4022 detobj.groupUUID = obj.GroupID;
4023 colliding.Add(detobj);
4024 }
4025 }
4026
4027 if (colliding.Count > 0)
4028 {
4029 StartCollidingMessage.Colliders = colliding;
4030
4031 foreach (SceneObjectGroup att in GetAttachments())
4032 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
4033 }
4034 }
4035
4036 if (endedColliders.Count > 0)
4037 {
4038 ColliderArgs EndCollidingMessage = new ColliderArgs();
4039 List<DetectedObject> colliding = new List<DetectedObject>();
4040 foreach (uint localId in endedColliders)
4041 {
4042 if (localId == 0)
4043 continue;
4044
4045 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4046 string data = "";
4047 if (obj != null)
4048 {
4049 DetectedObject detobj = new DetectedObject();
4050 detobj.keyUUID = obj.UUID;
4051 detobj.nameStr = obj.Name;
4052 detobj.ownerUUID = obj.OwnerID;
4053 detobj.posVector = obj.AbsolutePosition;
4054 detobj.rotQuat = obj.GetWorldRotation();
4055 detobj.velVector = obj.Velocity;
4056 detobj.colliderType = 0;
4057 detobj.groupUUID = obj.GroupID;
4058 colliding.Add(detobj);
4059 }
4060 }
4061
4062 if (colliding.Count > 0)
4063 {
4064 EndCollidingMessage.Colliders = colliding;
4065
4066 foreach (SceneObjectGroup att in GetAttachments())
4067 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4068 }
4069 }
4070
4071 if (thisHitColliders.Count > 0)
4072 {
4073 ColliderArgs CollidingMessage = new ColliderArgs();
4074 List<DetectedObject> colliding = new List<DetectedObject>();
4075 foreach (uint localId in thisHitColliders)
4076 {
4077 if (localId == 0)
4078 continue;
4079
4080 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4081 string data = "";
4082 if (obj != null)
4083 {
4084 DetectedObject detobj = new DetectedObject();
4085 detobj.keyUUID = obj.UUID;
4086 detobj.nameStr = obj.Name;
4087 detobj.ownerUUID = obj.OwnerID;
4088 detobj.posVector = obj.AbsolutePosition;
4089 detobj.rotQuat = obj.GetWorldRotation();
4090 detobj.velVector = obj.Velocity;
4091 detobj.colliderType = 0;
4092 detobj.groupUUID = obj.GroupID;
4093 colliding.Add(detobj);
4094 }
4095 }
4096
4097 if (colliding.Count > 0)
4098 {
4099 CollidingMessage.Colliders = colliding;
4100
4101 lock (m_attachments)
4102 {
4103 foreach (SceneObjectGroup att in m_attachments)
4104 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4105 }
4106 }
4107 }
4108 }
4109 finally
4110 {
4111 m_collisionEventFlag = false;
4112 }
4113 });
4114 }
4115
3860 private void TeleportFlagsDebug() { 4116 private void TeleportFlagsDebug() {
3861 4117
3862 // Some temporary debugging help to show all the TeleportFlags we have... 4118 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -3881,6 +4137,5 @@ namespace OpenSim.Region.Framework.Scenes
3881 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4137 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
3882 4138
3883 } 4139 }
3884
3885 } 4140 }
3886} 4141}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index e6b88a3..1cd8189 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -244,6 +244,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
244 sr.Close(); 244 sr.Close();
245 } 245 }
246 246
247 XmlNodeList keymotion = doc.GetElementsByTagName("KeyframeMotion");
248 if (keymotion.Count > 0)
249 sceneObject.RootPart.KeyframeMotion = KeyframeMotion.FromData(sceneObject, Convert.FromBase64String(keymotion[0].InnerText));
250 else
251 sceneObject.RootPart.KeyframeMotion = null;
252
247 // Script state may, or may not, exist. Not having any, is NOT 253 // Script state may, or may not, exist. Not having any, is NOT
248 // ever a problem. 254 // ever a problem.
249 sceneObject.LoadScriptState(doc); 255 sceneObject.LoadScriptState(doc);
@@ -347,6 +353,21 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
347 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 353 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
348 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 354 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
349 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 355 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
356
357 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
358 m_SOPXmlProcessors.Add("Force", ProcessForce);
359 m_SOPXmlProcessors.Add("Torque", ProcessTorque);
360 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
361
362
363 m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle);
364
365 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType);
366 m_SOPXmlProcessors.Add("Density", ProcessDensity);
367 m_SOPXmlProcessors.Add("Friction", ProcessFriction);
368 m_SOPXmlProcessors.Add("Bounce", ProcessBounce);
369 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier);
370
350 #endregion 371 #endregion
351 372
352 #region TaskInventoryXmlProcessors initialization 373 #region TaskInventoryXmlProcessors initialization
@@ -374,7 +395,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
374 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask); 395 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask);
375 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType); 396 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType);
376 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged); 397 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged);
377 398
378 #endregion 399 #endregion
379 400
380 #region ShapeXmlProcessors initialization 401 #region ShapeXmlProcessors initialization
@@ -569,6 +590,49 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
569 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty); 590 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty);
570 } 591 }
571 592
593 private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlTextReader reader)
594 {
595 obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty);
596 }
597
598 private static void ProcessDensity(SceneObjectPart obj, XmlTextReader reader)
599 {
600 obj.Density = reader.ReadElementContentAsFloat("Density", String.Empty);
601 }
602
603 private static void ProcessFriction(SceneObjectPart obj, XmlTextReader reader)
604 {
605 obj.Friction = reader.ReadElementContentAsFloat("Friction", String.Empty);
606 }
607
608 private static void ProcessBounce(SceneObjectPart obj, XmlTextReader reader)
609 {
610 obj.Bounciness = reader.ReadElementContentAsFloat("Bounce", String.Empty);
611 }
612
613 private static void ProcessGravityModifier(SceneObjectPart obj, XmlTextReader reader)
614 {
615 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty);
616 }
617
618 private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader)
619 {
620 bool errors = false;
621 SOPVehicle _vehicle = new SOPVehicle();
622
623 _vehicle.FromXml2(reader, out errors);
624
625 if (errors)
626 {
627 obj.sopVehicle = null;
628 m_log.DebugFormat(
629 "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.",
630 obj.Name, obj.UUID);
631 }
632 else
633 obj.sopVehicle = _vehicle;
634 }
635
572 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) 636 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader)
573 { 637 {
574 List<string> errorNodeNames; 638 List<string> errorNodeNames;
@@ -733,6 +797,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
733 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 797 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
734 } 798 }
735 799
800 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
801 {
802 obj.Buoyancy = (float)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
803 }
804
805 private static void ProcessForce(SceneObjectPart obj, XmlTextReader reader)
806 {
807 obj.Force = Util.ReadVector(reader, "Force");
808 }
809 private static void ProcessTorque(SceneObjectPart obj, XmlTextReader reader)
810 {
811 obj.Torque = Util.ReadVector(reader, "Torque");
812 }
813
814 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
815 {
816 obj.VolumeDetectActive = Util.ReadBoolean(reader);
817 }
818
736 #endregion 819 #endregion
737 820
738 #region TaskInventoryXmlProcessors 821 #region TaskInventoryXmlProcessors
@@ -1120,6 +1203,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1120 }); 1203 });
1121 1204
1122 writer.WriteEndElement(); 1205 writer.WriteEndElement();
1206
1207 if (sog.RootPart.KeyframeMotion != null)
1208 {
1209 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1210
1211 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1212 writer.WriteBase64(data, 0, data.Length);
1213 writer.WriteEndElement();
1214 }
1215
1123 writer.WriteEndElement(); 1216 writer.WriteEndElement();
1124 } 1217 }
1125 1218
@@ -1218,6 +1311,27 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1218 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1311 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1219 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1312 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1220 1313
1314 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1315
1316 WriteVector(writer, "Force", sop.Force);
1317 WriteVector(writer, "Torque", sop.Torque);
1318
1319 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1320
1321 if (sop.sopVehicle != null)
1322 sop.sopVehicle.ToXml2(writer);
1323
1324 if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType())
1325 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
1326 if (sop.Density != 1000.0f)
1327 writer.WriteElementString("Density", sop.Density.ToString().ToLower());
1328 if (sop.Friction != 0.6f)
1329 writer.WriteElementString("Friction", sop.Friction.ToString().ToLower());
1330 if (sop.Bounciness != 0.5f)
1331 writer.WriteElementString("Bounce", sop.Bounciness.ToString().ToLower());
1332 if (sop.GravityModifier != 1.0f)
1333 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
1334
1221 writer.WriteEndElement(); 1335 writer.WriteEndElement();
1222 } 1336 }
1223 1337
@@ -1487,12 +1601,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1487 { 1601 {
1488 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1602 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1489 1603
1490 if (reader.IsEmptyElement)
1491 {
1492 reader.Read();
1493 return tinv;
1494 }
1495
1496 reader.ReadStartElement(name, String.Empty); 1604 reader.ReadStartElement(name, String.Empty);
1497 1605
1498 while (reader.Name == "TaskInventoryItem") 1606 while (reader.Name == "TaskInventoryItem")
diff --git a/OpenSim/Region/Framework/Scenes/UndoState.cs b/OpenSim/Region/Framework/Scenes/UndoState.cs
index 860172c..7bbf1bd 100644
--- a/OpenSim/Region/Framework/Scenes/UndoState.cs
+++ b/OpenSim/Region/Framework/Scenes/UndoState.cs
@@ -27,202 +27,307 @@
27 27
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using System.Collections.Generic;
30using log4net; 31using log4net;
31using OpenMetaverse; 32using OpenMetaverse;
33using OpenSim.Framework;
32using OpenSim.Region.Framework.Interfaces; 34using OpenSim.Region.Framework.Interfaces;
33 35
34namespace OpenSim.Region.Framework.Scenes 36namespace OpenSim.Region.Framework.Scenes
35{ 37{
36 public class UndoState 38 public class UndoState
37 { 39 {
38// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 40 const int UNDOEXPIRESECONDS = 300; // undo expire time (nice to have it came from a ini later)
39
40 public Vector3 Position = Vector3.Zero;
41 public Vector3 Scale = Vector3.Zero;
42 public Quaternion Rotation = Quaternion.Identity;
43
44 /// <summary>
45 /// Is this undo state for an entire group?
46 /// </summary>
47 public bool ForGroup;
48 41
42 public ObjectChangeData data;
43 public DateTime creationtime;
49 /// <summary> 44 /// <summary>
50 /// Constructor. 45 /// Constructor.
51 /// </summary> 46 /// </summary>
52 /// <param name="part"></param> 47 /// <param name="part"></param>
53 /// <param name="forGroup">True if the undo is for an entire group</param> 48 /// <param name="change">bit field with what is changed</param>
54 public UndoState(SceneObjectPart part, bool forGroup) 49 ///
50 public UndoState(SceneObjectPart part, ObjectChangeType change)
55 { 51 {
56 if (part.ParentID == 0) 52 data = new ObjectChangeData();
57 { 53 data.change = change;
58 ForGroup = forGroup; 54 creationtime = DateTime.UtcNow;
59
60// if (ForGroup)
61 Position = part.ParentGroup.AbsolutePosition;
62// else
63// Position = part.OffsetPosition;
64
65// m_log.DebugFormat(
66// "[UNDO STATE]: Storing undo position {0} for root part", Position);
67 55
68 Rotation = part.RotationOffset; 56 if (part.ParentGroup.RootPart == part)
69 57 {
70// m_log.DebugFormat( 58 if ((change & ObjectChangeType.Position) != 0)
71// "[UNDO STATE]: Storing undo rotation {0} for root part", Rotation); 59 data.position = part.ParentGroup.AbsolutePosition;
72 60 if ((change & ObjectChangeType.Rotation) != 0)
73 Scale = part.Shape.Scale; 61 data.rotation = part.RotationOffset;
74 62 if ((change & ObjectChangeType.Scale) != 0)
75// m_log.DebugFormat( 63 data.scale = part.Shape.Scale;
76// "[UNDO STATE]: Storing undo scale {0} for root part", Scale);
77 } 64 }
78 else 65 else
79 { 66 {
80 Position = part.OffsetPosition; 67 if ((change & ObjectChangeType.Position) != 0)
81// m_log.DebugFormat( 68 data.position = part.OffsetPosition;
82// "[UNDO STATE]: Storing undo position {0} for child part", Position); 69 if ((change & ObjectChangeType.Rotation) != 0)
70 data.rotation = part.RotationOffset;
71 if ((change & ObjectChangeType.Scale) != 0)
72 data.scale = part.Shape.Scale;
73 }
74 }
75 /// <summary>
76 /// check if undo or redo is too old
77 /// </summary>
83 78
84 Rotation = part.RotationOffset; 79 public bool checkExpire()
85// m_log.DebugFormat( 80 {
86// "[UNDO STATE]: Storing undo rotation {0} for child part", Rotation); 81 TimeSpan t = DateTime.UtcNow - creationtime;
82 if (t.Seconds > UNDOEXPIRESECONDS)
83 return true;
84 return false;
85 }
87 86
88 Scale = part.Shape.Scale; 87 /// <summary>
89// m_log.DebugFormat( 88 /// updates undo or redo creation time to now
90// "[UNDO STATE]: Storing undo scale {0} for child part", Scale); 89 /// </summary>
91 } 90 public void updateExpire()
91 {
92 creationtime = DateTime.UtcNow;
92 } 93 }
93 94
94 /// <summary> 95 /// <summary>
95 /// Compare the relevant state in the given part to this state. 96 /// Compare the relevant state in the given part to this state.
96 /// </summary> 97 /// </summary>
97 /// <param name="part"></param> 98 /// <param name="part"></param>
98 /// <returns>true if both the part's position, rotation and scale match those in this undo state. False otherwise.</returns> 99 /// <returns>true what fiels and related data are equal, False otherwise.</returns>
99 public bool Compare(SceneObjectPart part) 100 ///
101 public bool Compare(SceneObjectPart part, ObjectChangeType change)
100 { 102 {
103 if (data.change != change) // if diferent targets, then they are diferent
104 return false;
105
101 if (part != null) 106 if (part != null)
102 { 107 {
103 if (part.ParentID == 0) 108 if (part.ParentID == 0)
104 return 109 {
105 Position == part.ParentGroup.AbsolutePosition 110 if ((change & ObjectChangeType.Position) != 0 && data.position != part.ParentGroup.AbsolutePosition)
106 && Rotation == part.RotationOffset 111 return false;
107 && Scale == part.Shape.Scale; 112 }
108 else 113 else
109 return 114 {
110 Position == part.OffsetPosition 115 if ((change & ObjectChangeType.Position) != 0 && data.position != part.OffsetPosition)
111 && Rotation == part.RotationOffset 116 return false;
112 && Scale == part.Shape.Scale; 117 }
113 } 118
119 if ((change & ObjectChangeType.Rotation) != 0 && data.rotation != part.RotationOffset)
120 return false;
121 if ((change & ObjectChangeType.Rotation) != 0 && data.scale == part.Shape.Scale)
122 return false;
123 return true;
114 124
125 }
115 return false; 126 return false;
116 } 127 }
117 128
118 public void PlaybackState(SceneObjectPart part) 129 /// <summary>
130 /// executes the undo or redo to a part or its group
131 /// </summary>
132 /// <param name="part"></param>
133 ///
134
135 public void PlayState(SceneObjectPart part)
119 { 136 {
120 part.Undoing = true; 137 part.Undoing = true;
121 138
122 if (part.ParentID == 0) 139 SceneObjectGroup grp = part.ParentGroup;
123 {
124// m_log.DebugFormat(
125// "[UNDO STATE]: Undoing position to {0} for root part {1} {2}",
126// Position, part.Name, part.LocalId);
127 140
128 if (Position != Vector3.Zero) 141 if (grp != null)
129 { 142 {
130 if (ForGroup) 143 grp.doChangeObject(part, data);
131 part.ParentGroup.AbsolutePosition = Position; 144 }
132 else 145 part.Undoing = false;
133 part.ParentGroup.UpdateRootPosition(Position); 146 }
134 } 147 }
135 148
136// m_log.DebugFormat( 149 public class UndoRedoState
137// "[UNDO STATE]: Undoing rotation {0} to {1} for root part {2} {3}", 150 {
138// part.RotationOffset, Rotation, part.Name, part.LocalId); 151 int size;
152 public LinkedList<UndoState> m_redo = new LinkedList<UndoState>();
153 public LinkedList<UndoState> m_undo = new LinkedList<UndoState>();
139 154
140 if (ForGroup) 155 /// <summary>
141 part.UpdateRotation(Rotation); 156 /// creates a new UndoRedoState with default states memory size
142 else 157 /// </summary>
143 part.ParentGroup.UpdateRootRotation(Rotation);
144 158
145 if (Scale != Vector3.Zero) 159 public UndoRedoState()
146 { 160 {
147// m_log.DebugFormat( 161 size = 5;
148// "[UNDO STATE]: Undoing scale {0} to {1} for root part {2} {3}", 162 }
149// part.Shape.Scale, Scale, part.Name, part.LocalId);
150 163
151 if (ForGroup) 164 /// <summary>
152 part.ParentGroup.GroupResize(Scale); 165 /// creates a new UndoRedoState with states memory having indicated size
153 else 166 /// </summary>
154 part.Resize(Scale); 167 /// <param name="size"></param>
155 }
156 168
157 part.ParentGroup.ScheduleGroupForTerseUpdate(); 169 public UndoRedoState(int _size)
158 } 170 {
171 if (_size < 3)
172 size = 3;
159 else 173 else
160 { 174 size = _size;
161 // Note: Updating these properties on sop automatically schedules an update if needed 175 }
162 if (Position != Vector3.Zero)
163 {
164// m_log.DebugFormat(
165// "[UNDO STATE]: Undoing position {0} to {1} for child part {2} {3}",
166// part.OffsetPosition, Position, part.Name, part.LocalId);
167 176
168 part.OffsetPosition = Position; 177 /// <summary>
169 } 178 /// returns number of undo entries in memory
179 /// </summary>
170 180
171// m_log.DebugFormat( 181 public int Count
172// "[UNDO STATE]: Undoing rotation {0} to {1} for child part {2} {3}", 182 {
173// part.RotationOffset, Rotation, part.Name, part.LocalId); 183 get { return m_undo.Count; }
184 }
174 185
175 part.UpdateRotation(Rotation); 186 /// <summary>
187 /// clears all undo and redo entries
188 /// </summary>
176 189
177 if (Scale != Vector3.Zero) 190 public void Clear()
191 {
192 m_undo.Clear();
193 m_redo.Clear();
194 }
195
196 /// <summary>
197 /// adds a new state undo to part or its group, with changes indicated by what bits
198 /// </summary>
199 /// <param name="part"></param>
200 /// <param name="change">bit field with what is changed</param>
201
202 public void StoreUndo(SceneObjectPart part, ObjectChangeType change)
203 {
204 lock (m_undo)
205 {
206 UndoState last;
207
208 if (m_redo.Count > 0) // last code seems to clear redo on every new undo
178 { 209 {
179// m_log.DebugFormat( 210 m_redo.Clear();
180// "[UNDO STATE]: Undoing scale {0} to {1} for child part {2} {3}", 211 }
181// part.Shape.Scale, Scale, part.Name, part.LocalId);
182 212
183 part.Resize(Scale); 213 if (m_undo.Count > 0)
214 {
215 // check expired entry
216 last = m_undo.First.Value;
217 if (last != null && last.checkExpire())
218 m_undo.Clear();
219 else
220 {
221 // see if we actually have a change
222 if (last != null)
223 {
224 if (last.Compare(part, change))
225 return;
226 }
227 }
184 } 228 }
185 }
186 229
187 part.Undoing = false; 230 // limite size
231 while (m_undo.Count >= size)
232 m_undo.RemoveLast();
233
234 UndoState nUndo = new UndoState(part, change);
235 m_undo.AddFirst(nUndo);
236 }
188 } 237 }
189 238
190 public void PlayfwdState(SceneObjectPart part) 239 /// <summary>
191 { 240 /// executes last state undo to part or its group
192 part.Undoing = true; 241 /// current state is pushed into redo
242 /// </summary>
243 /// <param name="part"></param>
193 244
194 if (part.ParentID == 0) 245 public void Undo(SceneObjectPart part)
246 {
247 lock (m_undo)
195 { 248 {
196 if (Position != Vector3.Zero) 249 UndoState nUndo;
197 part.ParentGroup.AbsolutePosition = Position;
198
199 if (Rotation != Quaternion.Identity)
200 part.UpdateRotation(Rotation);
201 250
202 if (Scale != Vector3.Zero) 251 // expire redo
252 if (m_redo.Count > 0)
203 { 253 {
204 if (ForGroup) 254 nUndo = m_redo.First.Value;
205 part.ParentGroup.GroupResize(Scale); 255 if (nUndo != null && nUndo.checkExpire())
206 else 256 m_redo.Clear();
207 part.Resize(Scale);
208 } 257 }
209 258
210 part.ParentGroup.ScheduleGroupForTerseUpdate(); 259 if (m_undo.Count > 0)
260 {
261 UndoState goback = m_undo.First.Value;
262 // check expired
263 if (goback != null && goback.checkExpire())
264 {
265 m_undo.Clear();
266 return;
267 }
268
269 if (goback != null)
270 {
271 m_undo.RemoveFirst();
272
273 // redo limite size
274 while (m_redo.Count >= size)
275 m_redo.RemoveLast();
276
277 nUndo = new UndoState(part, goback.data.change); // new value in part should it be full goback copy?
278 m_redo.AddFirst(nUndo);
279
280 goback.PlayState(part);
281 }
282 }
211 } 283 }
212 else 284 }
285
286 /// <summary>
287 /// executes last state redo to part or its group
288 /// current state is pushed into undo
289 /// </summary>
290 /// <param name="part"></param>
291
292 public void Redo(SceneObjectPart part)
293 {
294 lock (m_undo)
213 { 295 {
214 // Note: Updating these properties on sop automatically schedules an update if needed 296 UndoState nUndo;
215 if (Position != Vector3.Zero)
216 part.OffsetPosition = Position;
217 297
218 if (Rotation != Quaternion.Identity) 298 // expire undo
219 part.UpdateRotation(Rotation); 299 if (m_undo.Count > 0)
300 {
301 nUndo = m_undo.First.Value;
302 if (nUndo != null && nUndo.checkExpire())
303 m_undo.Clear();
304 }
220 305
221 if (Scale != Vector3.Zero) 306 if (m_redo.Count > 0)
222 part.Resize(Scale); 307 {
308 UndoState gofwd = m_redo.First.Value;
309 // check expired
310 if (gofwd != null && gofwd.checkExpire())
311 {
312 m_redo.Clear();
313 return;
314 }
315
316 if (gofwd != null)
317 {
318 m_redo.RemoveFirst();
319
320 // limite undo size
321 while (m_undo.Count >= size)
322 m_undo.RemoveLast();
323
324 nUndo = new UndoState(part, gofwd.data.change); // new value in part should it be full gofwd copy?
325 m_undo.AddFirst(nUndo);
326
327 gofwd.PlayState(part);
328 }
329 }
223 } 330 }
224
225 part.Undoing = false;
226 } 331 }
227 } 332 }
228 333
@@ -247,4 +352,4 @@ namespace OpenSim.Region.Framework.Scenes
247 m_terrainModule.UndoTerrain(m_terrainChannel); 352 m_terrainModule.UndoTerrain(m_terrainChannel);
248 } 353 }
249 } 354 }
250} \ No newline at end of file 355}
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index efb68a2..411e421 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -87,10 +87,6 @@ namespace OpenSim.Region.Framework.Scenes
87 /// <param name="assetUuids">The assets gathered</param> 87 /// <param name="assetUuids">The assets gathered</param>
88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids) 88 public void GatherAssetUuids(UUID assetUuid, AssetType assetType, IDictionary<UUID, AssetType> assetUuids)
89 { 89 {
90 // avoid infinite loops
91 if (assetUuids.ContainsKey(assetUuid))
92 return;
93
94 try 90 try
95 { 91 {
96 assetUuids[assetUuid] = assetType; 92 assetUuids[assetUuid] = assetType;