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.cs347
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs684
-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.cs1178
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs1131
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs804
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs420
-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, 5378 insertions, 1400 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 1334905..32f4eea 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>
@@ -238,5 +240,6 @@ namespace OpenSim.Region.Framework.Interfaces
238 /// A <see cref="Dictionary`2"/> 240 /// A <see cref="Dictionary`2"/>
239 /// </returns> 241 /// </returns>
240 Dictionary<UUID, string> GetScriptStates(); 242 Dictionary<UUID, string> GetScriptStates();
243 Dictionary<UUID, string> GetScriptStates(bool oldIDs);
241 } 244 }
242} 245}
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 fe3438e..741d233 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;
@@ -883,6 +887,26 @@ namespace OpenSim.Region.Framework.Scenes
883 } 887 }
884 } 888 }
885 } 889 }
890 public void TriggerTerrainUpdate()
891 {
892 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
893 if (handlerTerrainUpdate != null)
894 {
895 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
896 {
897 try
898 {
899 d();
900 }
901 catch (Exception e)
902 {
903 m_log.ErrorFormat(
904 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
905 e.Message, e.StackTrace);
906 }
907 }
908 }
909 }
886 910
887 public void TriggerTerrainTick() 911 public void TriggerTerrainTick()
888 { 912 {
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 5abd74f..6cf1067 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 {
125// m_log.DebugFormat(
126// "[LOCAL INVENTORY SERVICES CONNECTOR]: Found folder {0} type {1} for item {2}",
127// f.Name, (AssetType)f.Type, item.Name);
128
129 item.Folder = f.ID;
130 }
131 else
132 { 126 {
133 f = InventoryService.GetRootFolder(item.Owner); 127 folder = InventoryService.GetRootFolder(item.Owner);
134 if (f != null) 128
135 { 129 if (folder == null)
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(
@@ -1238,21 +1245,28 @@ namespace OpenSim.Region.Framework.Scenes
1238 return; 1245 return;
1239 } 1246 }
1240 1247
1241 if (part.OwnerID != destPart.OwnerID) 1248 // Can't transfer this
1249 //
1250 if (part.OwnerID != destPart.OwnerID && (srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1251 return;
1252
1253 bool overrideNoMod = false;
1254 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1255 overrideNoMod = true;
1256
1257 if (part.OwnerID != destPart.OwnerID && (destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1242 { 1258 {
1243 // Source must have transfer permissions 1259 // object cannot copy items to an object owned by a different owner
1244 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) 1260 // unless llAllowInventoryDrop has been called
1245 return;
1246 1261
1247 // Object cannot copy items to an object owned by a different owner 1262 return;
1248 // unless llAllowInventoryDrop has been called on the destination
1249 if ((destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1250 return;
1251 } 1263 }
1252 1264
1253 // 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
1254 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1266 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1267 {
1255 return; 1268 return;
1269 }
1256 1270
1257 TaskInventoryItem destTaskItem = new TaskInventoryItem(); 1271 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1258 1272
@@ -1308,6 +1322,14 @@ namespace OpenSim.Region.Framework.Scenes
1308 1322
1309 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)
1310 { 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
1311 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1333 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1312 1334
1313 UUID newFolderID = UUID.Random(); 1335 UUID newFolderID = UUID.Random();
@@ -1493,12 +1515,12 @@ namespace OpenSim.Region.Framework.Scenes
1493 agentTransactions.HandleTaskItemUpdateFromTransaction( 1515 agentTransactions.HandleTaskItemUpdateFromTransaction(
1494 remoteClient, part, transactionID, currentItem); 1516 remoteClient, part, transactionID, currentItem);
1495 1517
1496 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1518// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1497 remoteClient.SendAgentAlertMessage("Notecard saved", false); 1519// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1498 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1520// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1499 remoteClient.SendAgentAlertMessage("Script saved", false); 1521// remoteClient.SendAgentAlertMessage("Script saved", false);
1500 else 1522// else
1501 remoteClient.SendAgentAlertMessage("Item saved", false); 1523// remoteClient.SendAgentAlertMessage("Item saved", false);
1502 } 1524 }
1503 } 1525 }
1504 1526
@@ -1682,7 +1704,7 @@ namespace OpenSim.Region.Framework.Scenes
1682 } 1704 }
1683 1705
1684 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1706 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1685 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}"),
1686 agentID); 1708 agentID);
1687 AssetService.Store(asset); 1709 AssetService.Store(asset);
1688 1710
@@ -1838,23 +1860,32 @@ namespace OpenSim.Region.Framework.Scenes
1838 // build a list of eligible objects 1860 // build a list of eligible objects
1839 List<uint> deleteIDs = new List<uint>(); 1861 List<uint> deleteIDs = new List<uint>();
1840 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1862 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1841 1863 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1842 // Start with true for both, then remove the flags if objects
1843 // that we can't derez are part of the selection
1844 bool permissionToTake = true;
1845 bool permissionToTakeCopy = true;
1846 bool permissionToDelete = true;
1847 1864
1848 foreach (uint localID in localIDs) 1865 foreach (uint localID in localIDs)
1849 { 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
1850 // Invalid id 1873 // Invalid id
1851 SceneObjectPart part = GetSceneObjectPart(localID); 1874 SceneObjectPart part = GetSceneObjectPart(localID);
1852 if (part == null) 1875 if (part == null)
1876 {
1877 //Client still thinks the object exists, kill it
1878 deleteIDs.Add(localID);
1853 continue; 1879 continue;
1880 }
1854 1881
1855 // Already deleted by someone else 1882 // Already deleted by someone else
1856 if (part.ParentGroup.IsDeleted) 1883 if (part.ParentGroup.IsDeleted)
1884 {
1885 //Client still thinks the object exists, kill it
1886 deleteIDs.Add(localID);
1857 continue; 1887 continue;
1888 }
1858 1889
1859 // Can't delete child prims 1890 // Can't delete child prims
1860 if (part != part.ParentGroup.RootPart) 1891 if (part != part.ParentGroup.RootPart)
@@ -1862,9 +1893,6 @@ namespace OpenSim.Region.Framework.Scenes
1862 1893
1863 SceneObjectGroup grp = part.ParentGroup; 1894 SceneObjectGroup grp = part.ParentGroup;
1864 1895
1865 deleteIDs.Add(localID);
1866 deleteGroups.Add(grp);
1867
1868 if (remoteClient == null) 1896 if (remoteClient == null)
1869 { 1897 {
1870 // Autoreturn has a null client. Nothing else does. So 1898 // Autoreturn has a null client. Nothing else does. So
@@ -1881,81 +1909,193 @@ namespace OpenSim.Region.Framework.Scenes
1881 } 1909 }
1882 else 1910 else
1883 { 1911 {
1884 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 {
1885 permissionToTakeCopy = false; 1919 permissionToTakeCopy = false;
1886 1920 }
1887 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1921 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1888 permissionToTake = false; 1922 permissionToTake = false;
1889 1923
1890 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1924 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1891 permissionToDelete = false; 1925 permissionToDelete = false;
1892 } 1926 }
1893 }
1894 1927
1895 // Handle god perms 1928 // Handle god perms
1896 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1929 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1897 { 1930 {
1898 permissionToTake = true; 1931 permissionToTake = true;
1899 permissionToTakeCopy = true; 1932 permissionToTakeCopy = true;
1900 permissionToDelete = true; 1933 permissionToDelete = true;
1901 } 1934 }
1902 1935
1903 // 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
1904 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1937 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1905 permissionToDelete = false; 1938 permissionToDelete = false;
1906 1939
1907 // 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
1908 // Note: after this point, the permissionToTakeCopy flag 1941 // Note: after this point, the permissionToTakeCopy flag
1909 // becomes irrelevant. It already includes the permissionToTake 1942 // becomes irrelevant. It already includes the permissionToTake
1910 // permission and after excluding no copy items here, we can 1943 // permission and after excluding no copy items here, we can
1911 // just use that. 1944 // just use that.
1912 if (action == DeRezAction.TakeCopy) 1945 if (action == DeRezAction.TakeCopy)
1913 { 1946 {
1914 // If we don't have permission, stop right here 1947 // If we don't have permission, stop right here
1915 if (!permissionToTakeCopy) 1948 if (!permissionToTakeCopy)
1916 return; 1949 return;
1917 1950
1918 permissionToTake = true; 1951 permissionToTake = true;
1919 // Don't delete 1952 // Don't delete
1920 permissionToDelete = false; 1953 permissionToDelete = false;
1921 } 1954 }
1922 1955
1923 if (action == DeRezAction.Return) 1956 if (action == DeRezAction.Return)
1924 {
1925 if (remoteClient != null)
1926 { 1957 {
1927 if (Permissions.CanReturnObjects( 1958 if (remoteClient != null)
1928 null,
1929 remoteClient.AgentId,
1930 deleteGroups))
1931 { 1959 {
1932 permissionToTake = true; 1960 if (Permissions.CanReturnObjects(
1933 permissionToDelete = true; 1961 null,
1934 1962 remoteClient.AgentId,
1935 foreach (SceneObjectGroup g in deleteGroups) 1963 deleteGroups))
1936 { 1964 {
1937 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");
1938 } 1969 }
1939 } 1970 }
1971 else // Auto return passes through here with null agent
1972 {
1973 permissionToTake = true;
1974 permissionToDelete = true;
1975 }
1940 } 1976 }
1941 else // Auto return passes through here with null agent 1977
1978 if (permissionToTake && (!permissionToDelete))
1979 takeGroups.Add(grp);
1980
1981 if (permissionToDelete)
1942 { 1982 {
1943 permissionToTake = true; 1983 if (permissionToTake)
1944 permissionToDelete = true; 1984 deleteGroups.Add(grp);
1985 deleteIDs.Add(grp.LocalId);
1945 } 1986 }
1946 } 1987 }
1947 1988
1948 if (permissionToTake) 1989 SendKillObject(deleteIDs);
1990
1991 if (deleteGroups.Count > 0)
1949 { 1992 {
1993 foreach (SceneObjectGroup g in deleteGroups)
1994 deleteIDs.Remove(g.LocalId);
1995
1950 m_asyncSceneObjectDeleter.DeleteToInventory( 1996 m_asyncSceneObjectDeleter.DeleteToInventory(
1951 action, destinationID, deleteGroups, remoteClient, 1997 action, destinationID, deleteGroups, remoteClient,
1952 permissionToDelete); 1998 true);
1953 } 1999 }
1954 else if (permissionToDelete) 2000 if (takeGroups.Count > 0)
2001 {
2002 m_asyncSceneObjectDeleter.DeleteToInventory(
2003 action, destinationID, takeGroups, remoteClient,
2004 false);
2005 }
2006 if (deleteIDs.Count > 0)
1955 { 2007 {
1956 foreach (SceneObjectGroup g in deleteGroups) 2008 foreach (SceneObjectGroup g in deleteGroups)
1957 DeleteSceneObject(g, false); 2009 DeleteSceneObject(g, true);
2010 }
2011 }
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;
1958 } 2097 }
2098 return UUID.Zero;
1959 } 2099 }
1960 2100
1961 /// <summary> 2101 /// <summary>
@@ -2084,6 +2224,9 @@ namespace OpenSim.Region.Framework.Scenes
2084 2224
2085 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2225 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2086 { 2226 {
2227 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2228 return;
2229
2087 SceneObjectPart part = GetSceneObjectPart(objectID); 2230 SceneObjectPart part = GetSceneObjectPart(objectID);
2088 if (part == null) 2231 if (part == null)
2089 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 29825a2..df37b98 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -118,6 +118,7 @@ namespace OpenSim.Region.Framework.Scenes
118 // TODO: need to figure out how allow client agents but deny 118 // TODO: need to figure out how allow client agents but deny
119 // root agents when ACL denies access to root agent 119 // root agents when ACL denies access to root agent
120 public bool m_strictAccessControl = true; 120 public bool m_strictAccessControl = true;
121 public bool m_seeIntoBannedRegion = false;
121 public int MaxUndoCount = 5; 122 public int MaxUndoCount = 5;
122 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 123 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
123 public bool LoginLock = false; 124 public bool LoginLock = false;
@@ -133,12 +134,14 @@ namespace OpenSim.Region.Framework.Scenes
133 134
134 protected int m_splitRegionID; 135 protected int m_splitRegionID;
135 protected Timer m_restartWaitTimer = new Timer(); 136 protected Timer m_restartWaitTimer = new Timer();
137 protected Timer m_timerWatchdog = new Timer();
136 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 138 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
137 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 139 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
138 protected string m_simulatorVersion = "OpenSimulator Server"; 140 protected string m_simulatorVersion = "OpenSimulator Server";
139 protected ModuleLoader m_moduleLoader; 141 protected ModuleLoader m_moduleLoader;
140 protected AgentCircuitManager m_authenticateHandler; 142 protected AgentCircuitManager m_authenticateHandler;
141 protected SceneCommunicationService m_sceneGridService; 143 protected SceneCommunicationService m_sceneGridService;
144 protected ISnmpModule m_snmpService = null;
142 145
143 protected ISimulationDataService m_SimulationDataService; 146 protected ISimulationDataService m_SimulationDataService;
144 protected IEstateDataService m_EstateDataService; 147 protected IEstateDataService m_EstateDataService;
@@ -201,7 +204,7 @@ namespace OpenSim.Region.Framework.Scenes
201 private int m_update_events = 1; 204 private int m_update_events = 1;
202 private int m_update_backup = 200; 205 private int m_update_backup = 200;
203 private int m_update_terrain = 50; 206 private int m_update_terrain = 50;
204// private int m_update_land = 1; 207 private int m_update_land = 10;
205 private int m_update_coarse_locations = 50; 208 private int m_update_coarse_locations = 50;
206 209
207 private int agentMS; 210 private int agentMS;
@@ -220,6 +223,7 @@ namespace OpenSim.Region.Framework.Scenes
220 /// </summary> 223 /// </summary>
221 private int m_lastFrameTick; 224 private int m_lastFrameTick;
222 225
226 public bool CombineRegions = false;
223 /// <summary> 227 /// <summary>
224 /// Tick at which the last maintenance run occurred. 228 /// Tick at which the last maintenance run occurred.
225 /// </summary> 229 /// </summary>
@@ -250,6 +254,11 @@ namespace OpenSim.Region.Framework.Scenes
250 /// </summary> 254 /// </summary>
251 private int m_LastLogin; 255 private int m_LastLogin;
252 256
257 private int m_lastIncoming;
258 private int m_lastOutgoing;
259 private int m_hbRestarts = 0;
260
261
253 /// <summary> 262 /// <summary>
254 /// Thread that runs the scene loop. 263 /// Thread that runs the scene loop.
255 /// </summary> 264 /// </summary>
@@ -265,7 +274,7 @@ namespace OpenSim.Region.Framework.Scenes
265 private volatile bool m_shuttingDown; 274 private volatile bool m_shuttingDown;
266 275
267// private int m_lastUpdate; 276// private int m_lastUpdate;
268// private bool m_firstHeartbeat = true; 277 private bool m_firstHeartbeat = true;
269 278
270 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; 279 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
271 private bool m_reprioritizationEnabled = true; 280 private bool m_reprioritizationEnabled = true;
@@ -310,6 +319,19 @@ namespace OpenSim.Region.Framework.Scenes
310 get { return m_sceneGridService; } 319 get { return m_sceneGridService; }
311 } 320 }
312 321
322 public ISnmpModule SnmpService
323 {
324 get
325 {
326 if (m_snmpService == null)
327 {
328 m_snmpService = RequestModuleInterface<ISnmpModule>();
329 }
330
331 return m_snmpService;
332 }
333 }
334
313 public ISimulationDataService SimulationDataService 335 public ISimulationDataService SimulationDataService
314 { 336 {
315 get 337 get
@@ -592,6 +614,8 @@ namespace OpenSim.Region.Framework.Scenes
592 m_EstateDataService = estateDataService; 614 m_EstateDataService = estateDataService;
593 m_regionHandle = m_regInfo.RegionHandle; 615 m_regionHandle = m_regInfo.RegionHandle;
594 m_regionName = m_regInfo.RegionName; 616 m_regionName = m_regInfo.RegionName;
617 m_lastIncoming = 0;
618 m_lastOutgoing = 0;
595 619
596 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 620 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
597 m_asyncSceneObjectDeleter.Enabled = true; 621 m_asyncSceneObjectDeleter.Enabled = true;
@@ -672,98 +696,107 @@ namespace OpenSim.Region.Framework.Scenes
672 696
673 // Region config overrides global config 697 // Region config overrides global config
674 // 698 //
675 if (m_config.Configs["Startup"] != null) 699 try
676 { 700 {
677 IConfig startupConfig = m_config.Configs["Startup"]; 701 if (m_config.Configs["Startup"] != null)
678
679 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
680 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
681 if (!m_useBackup)
682 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
683
684 //Animation states
685 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
686
687 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
688 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
689
690 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
691 if (RegionInfo.NonphysPrimMax > 0)
692 { 702 {
693 m_maxNonphys = RegionInfo.NonphysPrimMax; 703 IConfig startupConfig = m_config.Configs["Startup"];
694 }
695 704
696 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); 705 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
706 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
707 if (!m_useBackup)
708 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
709
710 //Animation states
711 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
697 712
698 if (RegionInfo.PhysPrimMax > 0) 713 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
699 { 714 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
700 m_maxPhys = RegionInfo.PhysPrimMax;
701 }
702 715
703 // Here, if clamping is requested in either global or 716 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
704 // local config, it will be used 717 if (RegionInfo.NonphysPrimMax > 0)
705 // 718 {
706 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize); 719 m_maxNonphys = RegionInfo.NonphysPrimMax;
707 if (RegionInfo.ClampPrimSize) 720 }
708 {
709 m_clampPrimSize = true;
710 }
711 721
712 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 722 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
713 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
714 m_dontPersistBefore =
715 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
716 m_dontPersistBefore *= 10000000;
717 m_persistAfter =
718 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
719 m_persistAfter *= 10000000;
720 723
721 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 724 if (RegionInfo.PhysPrimMax > 0)
725 {
726 m_maxPhys = RegionInfo.PhysPrimMax;
727 }
722 728
723 IConfig packetConfig = m_config.Configs["PacketPool"]; 729 // Here, if clamping is requested in either global or
724 if (packetConfig != null) 730 // local config, it will be used
725 { 731 //
726 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); 732 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
727 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); 733 if (RegionInfo.ClampPrimSize)
728 } 734 {
735 m_clampPrimSize = true;
736 }
729 737
730 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 738 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
739 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
740 m_dontPersistBefore =
741 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
742 m_dontPersistBefore *= 10000000;
743 m_persistAfter =
744 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
745 m_persistAfter *= 10000000;
731 746
732 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 747 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
733 if (m_generateMaptiles) 748 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
734 { 749
735 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0); 750 IConfig packetConfig = m_config.Configs["PacketPool"];
736 if (maptileRefresh != 0) 751 if (packetConfig != null)
737 { 752 {
738 m_mapGenerationTimer.Interval = maptileRefresh * 1000; 753 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
739 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister; 754 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
740 m_mapGenerationTimer.AutoReset = true;
741 m_mapGenerationTimer.Start();
742 } 755 }
743 }
744 else
745 {
746 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
747 UUID tileID;
748 756
749 if (UUID.TryParse(tile, out tileID)) 757 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
758 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
759 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
760
761 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
762 if (m_generateMaptiles)
750 { 763 {
751 RegionInfo.RegionSettings.TerrainImageID = tileID; 764 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
765 if (maptileRefresh != 0)
766 {
767 m_mapGenerationTimer.Interval = maptileRefresh * 1000;
768 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister;
769 m_mapGenerationTimer.AutoReset = true;
770 m_mapGenerationTimer.Start();
771 }
752 } 772 }
753 } 773 else
774 {
775 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
776 UUID tileID;
754 777
755 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime); 778 if (UUID.TryParse(tile, out tileID))
756 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup); 779 {
757 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 780 RegionInfo.RegionSettings.TerrainImageID = tileID;
758 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement); 781 }
759 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events); 782 }
760 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
761 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
762 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
763 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
764 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
765 783
766 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates); 784 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
785 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup);
786 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
787 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement);
788 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events);
789 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
790 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
791 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
792 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
793 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
794 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates);
795 }
796 }
797 catch (Exception e)
798 {
799 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
767 } 800 }
768 801
769 #endregion Region Config 802 #endregion Region Config
@@ -1194,7 +1227,22 @@ namespace OpenSim.Region.Framework.Scenes
1194 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1227 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1195 if (m_heartbeatThread != null) 1228 if (m_heartbeatThread != null)
1196 { 1229 {
1230 m_hbRestarts++;
1231 if(m_hbRestarts > 10)
1232 Environment.Exit(1);
1233 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1234
1235//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1236//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1237//proc.EnableRaisingEvents=false;
1238//proc.StartInfo.FileName = "/bin/kill";
1239//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1240//proc.Start();
1241//proc.WaitForExit();
1242//Thread.Sleep(1000);
1243//Environment.Exit(1);
1197 m_heartbeatThread.Abort(); 1244 m_heartbeatThread.Abort();
1245 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1198 m_heartbeatThread = null; 1246 m_heartbeatThread = null;
1199 } 1247 }
1200// m_lastUpdate = Util.EnvironmentTickCount(); 1248// m_lastUpdate = Util.EnvironmentTickCount();
@@ -1507,6 +1555,8 @@ namespace OpenSim.Region.Framework.Scenes
1507 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); 1555 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc);
1508 maintc = (int)(MinFrameTime * 1000) - maintc; 1556 maintc = (int)(MinFrameTime * 1000) - maintc;
1509 1557
1558 m_firstHeartbeat = false;
1559
1510 if (maintc > 0) 1560 if (maintc > 0)
1511 Thread.Sleep(maintc); 1561 Thread.Sleep(maintc);
1512 1562
@@ -1536,9 +1586,9 @@ namespace OpenSim.Region.Framework.Scenes
1536 1586
1537 private void CheckAtTargets() 1587 private void CheckAtTargets()
1538 { 1588 {
1539 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1589 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1540 lock (m_groupsWithTargets) 1590 lock (m_groupsWithTargets)
1541 objs = m_groupsWithTargets.Values; 1591 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1542 1592
1543 foreach (SceneObjectGroup entry in objs) 1593 foreach (SceneObjectGroup entry in objs)
1544 entry.checkAtTargets(); 1594 entry.checkAtTargets();
@@ -1619,7 +1669,7 @@ namespace OpenSim.Region.Framework.Scenes
1619 msg.fromAgentName = "Server"; 1669 msg.fromAgentName = "Server";
1620 msg.dialog = (byte)19; // Object msg 1670 msg.dialog = (byte)19; // Object msg
1621 msg.fromGroup = false; 1671 msg.fromGroup = false;
1622 msg.offline = (byte)0; 1672 msg.offline = (byte)1;
1623 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1673 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1624 msg.Position = Vector3.Zero; 1674 msg.Position = Vector3.Zero;
1625 msg.RegionID = RegionInfo.RegionID.Guid; 1675 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1857,14 +1907,24 @@ namespace OpenSim.Region.Framework.Scenes
1857 /// <returns></returns> 1907 /// <returns></returns>
1858 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1908 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1859 { 1909 {
1910
1911 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1912 Vector3 wpos = Vector3.Zero;
1913 // Check for water surface intersection from above
1914 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1915 {
1916 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1917 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1918 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1919 wpos.Z = wheight;
1920 }
1921
1860 Vector3 pos = Vector3.Zero; 1922 Vector3 pos = Vector3.Zero;
1861 if (RayEndIsIntersection == (byte)1) 1923 if (RayEndIsIntersection == (byte)1)
1862 { 1924 {
1863 pos = RayEnd; 1925 pos = RayEnd;
1864 return pos;
1865 } 1926 }
1866 1927 else if (RayTargetID != UUID.Zero)
1867 if (RayTargetID != UUID.Zero)
1868 { 1928 {
1869 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1929 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1870 1930
@@ -1886,7 +1946,7 @@ namespace OpenSim.Region.Framework.Scenes
1886 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1946 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1887 1947
1888 // Un-comment out the following line to Get Raytrace results printed to the console. 1948 // Un-comment out the following line to Get Raytrace results printed to the console.
1889 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1949 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1890 float ScaleOffset = 0.5f; 1950 float ScaleOffset = 0.5f;
1891 1951
1892 // If we hit something 1952 // If we hit something
@@ -1909,13 +1969,10 @@ namespace OpenSim.Region.Framework.Scenes
1909 //pos.Z -= 0.25F; 1969 //pos.Z -= 0.25F;
1910 1970
1911 } 1971 }
1912
1913 return pos;
1914 } 1972 }
1915 else 1973 else
1916 { 1974 {
1917 // We don't have a target here, so we're going to raytrace all the objects in the scene. 1975 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1918
1919 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 1976 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1920 1977
1921 // Un-comment the following line to print the raytrace results to the console. 1978 // Un-comment the following line to print the raytrace results to the console.
@@ -1924,13 +1981,12 @@ namespace OpenSim.Region.Framework.Scenes
1924 if (ei.HitTF) 1981 if (ei.HitTF)
1925 { 1982 {
1926 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 1983 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1927 } else 1984 }
1985 else
1928 { 1986 {
1929 // fall back to our stupid functionality 1987 // fall back to our stupid functionality
1930 pos = RayEnd; 1988 pos = RayEnd;
1931 } 1989 }
1932
1933 return pos;
1934 } 1990 }
1935 } 1991 }
1936 else 1992 else
@@ -1941,8 +1997,12 @@ namespace OpenSim.Region.Framework.Scenes
1941 //increase height so its above the ground. 1997 //increase height so its above the ground.
1942 //should be getting the normal of the ground at the rez point and using that? 1998 //should be getting the normal of the ground at the rez point and using that?
1943 pos.Z += scale.Z / 2f; 1999 pos.Z += scale.Z / 2f;
1944 return pos; 2000// return pos;
1945 } 2001 }
2002
2003 // check against posible water intercept
2004 if (wpos.Z > pos.Z) pos = wpos;
2005 return pos;
1946 } 2006 }
1947 2007
1948 2008
@@ -2032,7 +2092,10 @@ namespace OpenSim.Region.Framework.Scenes
2032 public bool AddRestoredSceneObject( 2092 public bool AddRestoredSceneObject(
2033 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2093 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2034 { 2094 {
2035 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2095 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
2096 if (result)
2097 sceneObject.IsDeleted = false;
2098 return result;
2036 } 2099 }
2037 2100
2038 /// <summary> 2101 /// <summary>
@@ -2124,6 +2187,15 @@ namespace OpenSim.Region.Framework.Scenes
2124 /// </summary> 2187 /// </summary>
2125 public void DeleteAllSceneObjects() 2188 public void DeleteAllSceneObjects()
2126 { 2189 {
2190 DeleteAllSceneObjects(false);
2191 }
2192
2193 /// <summary>
2194 /// Delete every object from the scene. This does not include attachments worn by avatars.
2195 /// </summary>
2196 public void DeleteAllSceneObjects(bool exceptNoCopy)
2197 {
2198 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2127 lock (Entities) 2199 lock (Entities)
2128 { 2200 {
2129 EntityBase[] entities = Entities.GetEntities(); 2201 EntityBase[] entities = Entities.GetEntities();
@@ -2132,11 +2204,24 @@ namespace OpenSim.Region.Framework.Scenes
2132 if (e is SceneObjectGroup) 2204 if (e is SceneObjectGroup)
2133 { 2205 {
2134 SceneObjectGroup sog = (SceneObjectGroup)e; 2206 SceneObjectGroup sog = (SceneObjectGroup)e;
2135 if (!sog.IsAttachment) 2207 if (sog != null && !sog.IsAttachment)
2136 DeleteSceneObject((SceneObjectGroup)e, false); 2208 {
2209 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2210 {
2211 DeleteSceneObject((SceneObjectGroup)e, false);
2212 }
2213 else
2214 {
2215 toReturn.Add((SceneObjectGroup)e);
2216 }
2217 }
2137 } 2218 }
2138 } 2219 }
2139 } 2220 }
2221 if (toReturn.Count > 0)
2222 {
2223 returnObjects(toReturn.ToArray(), UUID.Zero);
2224 }
2140 } 2225 }
2141 2226
2142 /// <summary> 2227 /// <summary>
@@ -2177,6 +2262,8 @@ namespace OpenSim.Region.Framework.Scenes
2177 } 2262 }
2178 2263
2179 group.DeleteGroupFromScene(silent); 2264 group.DeleteGroupFromScene(silent);
2265 if (!silent)
2266 SendKillObject(new List<uint>() { group.LocalId });
2180 2267
2181// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2268// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2182 } 2269 }
@@ -2466,6 +2553,8 @@ namespace OpenSim.Region.Framework.Scenes
2466 2553
2467 if (newPosition != Vector3.Zero) 2554 if (newPosition != Vector3.Zero)
2468 newObject.RootPart.GroupPosition = newPosition; 2555 newObject.RootPart.GroupPosition = newPosition;
2556 if (newObject.RootPart.KeyframeMotion != null)
2557 newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2469 2558
2470 if (!AddSceneObject(newObject)) 2559 if (!AddSceneObject(newObject))
2471 { 2560 {
@@ -2534,10 +2623,17 @@ namespace OpenSim.Region.Framework.Scenes
2534 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2623 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2535 public bool AddSceneObject(SceneObjectGroup sceneObject) 2624 public bool AddSceneObject(SceneObjectGroup sceneObject)
2536 { 2625 {
2626 if (sceneObject.OwnerID == UUID.Zero)
2627 {
2628 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2629 return false;
2630 }
2631
2537 // If the user is banned, we won't let any of their objects 2632 // If the user is banned, we won't let any of their objects
2538 // enter. Period. 2633 // enter. Period.
2539 // 2634 //
2540 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2635 int flags = GetUserFlags(sceneObject.OwnerID);
2636 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2541 { 2637 {
2542 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2638 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2543 2639
@@ -2583,12 +2679,23 @@ namespace OpenSim.Region.Framework.Scenes
2583 } 2679 }
2584 else 2680 else
2585 { 2681 {
2682 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2586 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2683 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2587 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2684 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2588 } 2685 }
2686 if (sceneObject.OwnerID == UUID.Zero)
2687 {
2688 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2689 return false;
2690 }
2589 } 2691 }
2590 else 2692 else
2591 { 2693 {
2694 if (sceneObject.OwnerID == UUID.Zero)
2695 {
2696 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2697 return false;
2698 }
2592 AddRestoredSceneObject(sceneObject, true, false); 2699 AddRestoredSceneObject(sceneObject, true, false);
2593 2700
2594 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2701 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2617,6 +2724,24 @@ namespace OpenSim.Region.Framework.Scenes
2617 return 2; // StateSource.PrimCrossing 2724 return 2; // StateSource.PrimCrossing
2618 } 2725 }
2619 2726
2727 public int GetUserFlags(UUID user)
2728 {
2729 //Unfortunately the SP approach means that the value is cached until region is restarted
2730 /*
2731 ScenePresence sp;
2732 if (TryGetScenePresence(user, out sp))
2733 {
2734 return sp.UserFlags;
2735 }
2736 else
2737 {
2738 */
2739 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2740 if (uac == null)
2741 return 0;
2742 return uac.UserFlags;
2743 //}
2744 }
2620 #endregion 2745 #endregion
2621 2746
2622 #region Add/Remove Avatar Methods 2747 #region Add/Remove Avatar Methods
@@ -2630,7 +2755,7 @@ namespace OpenSim.Region.Framework.Scenes
2630 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 2755 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2631 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2756 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2632 2757
2633// CheckHeartbeat(); 2758 CheckHeartbeat();
2634 2759
2635 ScenePresence sp = GetScenePresence(client.AgentId); 2760 ScenePresence sp = GetScenePresence(client.AgentId);
2636 2761
@@ -2683,7 +2808,13 @@ namespace OpenSim.Region.Framework.Scenes
2683 2808
2684 EventManager.TriggerOnNewClient(client); 2809 EventManager.TriggerOnNewClient(client);
2685 if (vialogin) 2810 if (vialogin)
2811 {
2686 EventManager.TriggerOnClientLogin(client); 2812 EventManager.TriggerOnClientLogin(client);
2813 // Send initial parcel data
2814 Vector3 pos = sp.AbsolutePosition;
2815 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2816 land.SendLandUpdateToClient(client);
2817 }
2687 2818
2688 return sp; 2819 return sp;
2689 } 2820 }
@@ -2773,19 +2904,12 @@ namespace OpenSim.Region.Framework.Scenes
2773 // and the scene presence and the client, if they exist 2904 // and the scene presence and the client, if they exist
2774 try 2905 try
2775 { 2906 {
2776 // We need to wait for the client to make UDP contact first. 2907 ScenePresence sp = GetScenePresence(agentID);
2777 // It's the UDP contact that creates the scene presence 2908 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2778 ScenePresence sp = WaitGetScenePresence(agentID); 2909
2779 if (sp != null) 2910 if (sp != null)
2780 {
2781 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2782
2783 sp.ControllingClient.Close(); 2911 sp.ControllingClient.Close();
2784 } 2912
2785 else
2786 {
2787 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2788 }
2789 // BANG! SLASH! 2913 // BANG! SLASH!
2790 m_authenticateHandler.RemoveCircuit(agentID); 2914 m_authenticateHandler.RemoveCircuit(agentID);
2791 2915
@@ -2830,6 +2954,8 @@ namespace OpenSim.Region.Framework.Scenes
2830 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 2954 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
2831 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 2955 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
2832 2956
2957 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
2958
2833 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 2959 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
2834 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 2960 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
2835 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 2961 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -2886,6 +3012,7 @@ namespace OpenSim.Region.Framework.Scenes
2886 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3012 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2887 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3013 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2888 client.OnCopyInventoryItem += CopyInventoryItem; 3014 client.OnCopyInventoryItem += CopyInventoryItem;
3015 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2889 client.OnMoveInventoryItem += MoveInventoryItem; 3016 client.OnMoveInventoryItem += MoveInventoryItem;
2890 client.OnRemoveInventoryItem += RemoveInventoryItem; 3017 client.OnRemoveInventoryItem += RemoveInventoryItem;
2891 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3018 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2957,6 +3084,8 @@ namespace OpenSim.Region.Framework.Scenes
2957 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3084 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
2958 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3085 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
2959 3086
3087 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3088
2960 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3089 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2961 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3090 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2962 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3091 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3059,15 +3188,16 @@ namespace OpenSim.Region.Framework.Scenes
3059 /// </summary> 3188 /// </summary>
3060 /// <param name="agentId">The avatar's Unique ID</param> 3189 /// <param name="agentId">The avatar's Unique ID</param>
3061 /// <param name="client">The IClientAPI for the client</param> 3190 /// <param name="client">The IClientAPI for the client</param>
3062 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3191 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
3063 { 3192 {
3064 if (m_teleportModule != null) 3193 if (m_teleportModule != null)
3065 m_teleportModule.TeleportHome(agentId, client); 3194 return m_teleportModule.TeleportHome(agentId, client);
3066 else 3195 else
3067 { 3196 {
3068 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3197 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
3069 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3198 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
3070 } 3199 }
3200 return false;
3071 } 3201 }
3072 3202
3073 /// <summary> 3203 /// <summary>
@@ -3177,6 +3307,16 @@ namespace OpenSim.Region.Framework.Scenes
3177 /// <param name="flags"></param> 3307 /// <param name="flags"></param>
3178 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3308 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3179 { 3309 {
3310 //Add half the avatar's height so that the user doesn't fall through prims
3311 ScenePresence presence;
3312 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3313 {
3314 if (presence.Appearance != null)
3315 {
3316 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3317 }
3318 }
3319
3180 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3320 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3181 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3321 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3182 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3322 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3245,8 +3385,9 @@ namespace OpenSim.Region.Framework.Scenes
3245 regions.Remove(RegionInfo.RegionHandle); 3385 regions.Remove(RegionInfo.RegionHandle);
3246 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3386 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3247 } 3387 }
3248 3388 m_log.Debug("[Scene] Beginning ClientClosed");
3249 m_eventManager.TriggerClientClosed(agentID, this); 3389 m_eventManager.TriggerClientClosed(agentID, this);
3390 m_log.Debug("[Scene] Finished ClientClosed");
3250 } 3391 }
3251 catch (NullReferenceException) 3392 catch (NullReferenceException)
3252 { 3393 {
@@ -3308,9 +3449,10 @@ namespace OpenSim.Region.Framework.Scenes
3308 { 3449 {
3309 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3450 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3310 } 3451 }
3311 3452 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3312 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3453 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3313// CleanDroppedAttachments(); 3454// CleanDroppedAttachments();
3455 m_log.Debug("[Scene] The avatar has left the building");
3314 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3456 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3315 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3457 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3316 } 3458 }
@@ -3432,13 +3574,16 @@ namespace OpenSim.Region.Framework.Scenes
3432 sp = null; 3574 sp = null;
3433 } 3575 }
3434 3576
3435 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3436 3577
3437 //On login test land permisions 3578 //On login test land permisions
3438 if (vialogin) 3579 if (vialogin)
3439 { 3580 {
3440 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3581 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3582 if (cache != null)
3583 cache.Remove(agent.firstname + " " + agent.lastname);
3584 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3441 { 3585 {
3586 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3442 return false; 3587 return false;
3443 } 3588 }
3444 } 3589 }
@@ -3462,8 +3607,13 @@ namespace OpenSim.Region.Framework.Scenes
3462 3607
3463 try 3608 try
3464 { 3609 {
3465 if (!AuthorizeUser(agent, out reason)) 3610 // Always check estate if this is a login. Always
3466 return false; 3611 // check if banned regions are to be blacked out.
3612 if (vialogin || (!m_seeIntoBannedRegion))
3613 {
3614 if (!AuthorizeUser(agent, out reason))
3615 return false;
3616 }
3467 } 3617 }
3468 catch (Exception e) 3618 catch (Exception e)
3469 { 3619 {
@@ -3589,6 +3739,8 @@ namespace OpenSim.Region.Framework.Scenes
3589 } 3739 }
3590 3740
3591 // Honor parcel landing type and position. 3741 // Honor parcel landing type and position.
3742 /*
3743 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3592 if (land != null) 3744 if (land != null)
3593 { 3745 {
3594 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3746 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3596,26 +3748,34 @@ namespace OpenSim.Region.Framework.Scenes
3596 agent.startpos = land.LandData.UserLocation; 3748 agent.startpos = land.LandData.UserLocation;
3597 } 3749 }
3598 } 3750 }
3751 */// This is now handled properly in ScenePresence.MakeRootAgent
3599 } 3752 }
3600 3753
3601 return true; 3754 return true;
3602 } 3755 }
3603 3756
3604 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3757 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3605 { 3758 {
3606 3759 reason = String.Empty;
3607 bool banned = land.IsBannedFromLand(agent.AgentID); 3760 if (Permissions.IsGod(agentID))
3608 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3761 return true;
3762
3763 ILandObject land = LandChannel.GetLandObject(posX, posY);
3764 if (land == null)
3765 return false;
3766
3767 bool banned = land.IsBannedFromLand(agentID);
3768 bool restricted = land.IsRestrictedFromLand(agentID);
3609 3769
3610 if (banned || restricted) 3770 if (banned || restricted)
3611 { 3771 {
3612 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3772 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3613 if (nearestParcel != null) 3773 if (nearestParcel != null)
3614 { 3774 {
3615 //Move agent to nearest allowed 3775 //Move agent to nearest allowed
3616 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3776 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3617 agent.startpos.X = newPosition.X; 3777 posX = newPosition.X;
3618 agent.startpos.Y = newPosition.Y; 3778 posY = newPosition.Y;
3619 } 3779 }
3620 else 3780 else
3621 { 3781 {
@@ -3677,7 +3837,7 @@ namespace OpenSim.Region.Framework.Scenes
3677 3837
3678 if (!m_strictAccessControl) return true; 3838 if (!m_strictAccessControl) return true;
3679 if (Permissions.IsGod(agent.AgentID)) return true; 3839 if (Permissions.IsGod(agent.AgentID)) return true;
3680 3840
3681 if (AuthorizationService != null) 3841 if (AuthorizationService != null)
3682 { 3842 {
3683 if (!AuthorizationService.IsAuthorizedForRegion( 3843 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3692,7 +3852,7 @@ namespace OpenSim.Region.Framework.Scenes
3692 3852
3693 if (m_regInfo.EstateSettings != null) 3853 if (m_regInfo.EstateSettings != null)
3694 { 3854 {
3695 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3855 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3696 { 3856 {
3697 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3857 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3698 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3858 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3884,6 +4044,13 @@ namespace OpenSim.Region.Framework.Scenes
3884 4044
3885 // We have to wait until the viewer contacts this region after receiving EAC. 4045 // We have to wait until the viewer contacts this region after receiving EAC.
3886 // That calls AddNewClient, which finally creates the ScenePresence 4046 // That calls AddNewClient, which finally creates the ScenePresence
4047 int flags = GetUserFlags(cAgentData.AgentID);
4048 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4049 {
4050 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4051 return false;
4052 }
4053
3887 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4054 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3888 if (nearestParcel == null) 4055 if (nearestParcel == null)
3889 { 4056 {
@@ -3965,12 +4132,22 @@ namespace OpenSim.Region.Framework.Scenes
3965 return false; 4132 return false;
3966 } 4133 }
3967 4134
4135 public bool IncomingCloseAgent(UUID agentID)
4136 {
4137 return IncomingCloseAgent(agentID, false);
4138 }
4139
4140 public bool IncomingCloseChildAgent(UUID agentID)
4141 {
4142 return IncomingCloseAgent(agentID, true);
4143 }
4144
3968 /// <summary> 4145 /// <summary>
3969 /// Tell a single agent to disconnect from the region. 4146 /// Tell a single agent to disconnect from the region.
3970 /// </summary> 4147 /// </summary>
3971 /// <param name="regionHandle"></param>
3972 /// <param name="agentID"></param> 4148 /// <param name="agentID"></param>
3973 public bool IncomingCloseAgent(UUID agentID) 4149 /// <param name="childOnly"></param>
4150 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
3974 { 4151 {
3975 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4152 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
3976 4153
@@ -3982,7 +4159,7 @@ namespace OpenSim.Region.Framework.Scenes
3982 { 4159 {
3983 m_sceneGraph.removeUserCount(false); 4160 m_sceneGraph.removeUserCount(false);
3984 } 4161 }
3985 else 4162 else if (!childOnly)
3986 { 4163 {
3987 m_sceneGraph.removeUserCount(true); 4164 m_sceneGraph.removeUserCount(true);
3988 } 4165 }
@@ -3998,9 +4175,12 @@ namespace OpenSim.Region.Framework.Scenes
3998 } 4175 }
3999 else 4176 else
4000 presence.ControllingClient.SendShutdownConnectionNotice(); 4177 presence.ControllingClient.SendShutdownConnectionNotice();
4178 presence.ControllingClient.Close(false);
4179 }
4180 else if (!childOnly)
4181 {
4182 presence.ControllingClient.Close(true);
4001 } 4183 }
4002
4003 presence.ControllingClient.Close();
4004 return true; 4184 return true;
4005 } 4185 }
4006 4186
@@ -4582,35 +4762,81 @@ namespace OpenSim.Region.Framework.Scenes
4582 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4762 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4583 } 4763 }
4584 4764
4585 public int GetHealth() 4765 public int GetHealth(out int flags, out string message)
4586 { 4766 {
4587 // Returns: 4767 // Returns:
4588 // 1 = sim is up and accepting http requests. The heartbeat has 4768 // 1 = sim is up and accepting http requests. The heartbeat has
4589 // stopped and the sim is probably locked up, but a remote 4769 // stopped and the sim is probably locked up, but a remote
4590 // admin restart may succeed 4770 // admin restart may succeed
4591 // 4771 //
4592 // 2 = Sim is up and the heartbeat is running. The sim is likely 4772 // 2 = Sim is up and the heartbeat is running. The sim is likely
4593 // usable for people within and logins _may_ work 4773 // usable for people within
4774 //
4775 // 3 = Sim is up and one packet thread is running. Sim is
4776 // unstable and will not accept new logins
4594 // 4777 //
4595 // 3 = We have seen a new user enter within the past 4 minutes 4778 // 4 = Sim is up and both packet threads are running. Sim is
4779 // likely usable
4780 //
4781 // 5 = We have seen a new user enter within the past 4 minutes
4596 // which can be seen as positive confirmation of sim health 4782 // which can be seen as positive confirmation of sim health
4597 // 4783 //
4784
4785 flags = 0;
4786 message = String.Empty;
4787
4788 CheckHeartbeat();
4789
4790 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4791 {
4792 // We're still starting
4793 // 0 means "in startup", it can't happen another way, since
4794 // to get here, we must be able to accept http connections
4795 return 0;
4796 }
4797
4598 int health=1; // Start at 1, means we're up 4798 int health=1; // Start at 1, means we're up
4599 4799
4600 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 4800 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000)
4601 health += 1; 4801 {
4802 health+=1;
4803 flags |= 1;
4804 }
4805
4806 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4807 {
4808 health+=1;
4809 flags |= 2;
4810 }
4811
4812 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4813 {
4814 health+=1;
4815 flags |= 4;
4816 }
4602 else 4817 else
4818 {
4819int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4820System.Diagnostics.Process proc = new System.Diagnostics.Process();
4821proc.EnableRaisingEvents=false;
4822proc.StartInfo.FileName = "/bin/kill";
4823proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4824proc.Start();
4825proc.WaitForExit();
4826Thread.Sleep(1000);
4827Environment.Exit(1);
4828 }
4829
4830 if (flags != 7)
4603 return health; 4831 return health;
4604 4832
4605 // A login in the last 4 mins? We can't be doing too badly 4833 // A login in the last 4 mins? We can't be doing too badly
4606 // 4834 //
4607 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4835 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4608 health++; 4836 health++;
4609 else 4837 else
4610 return health; 4838 return health;
4611 4839
4612// CheckHeartbeat();
4613
4614 return health; 4840 return health;
4615 } 4841 }
4616 4842
@@ -4698,7 +4924,7 @@ namespace OpenSim.Region.Framework.Scenes
4698 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 4924 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
4699 if (wasUsingPhysics) 4925 if (wasUsingPhysics)
4700 { 4926 {
4701 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 4927 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
4702 } 4928 }
4703 } 4929 }
4704 4930
@@ -4797,14 +5023,14 @@ namespace OpenSim.Region.Framework.Scenes
4797 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5023 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
4798 } 5024 }
4799 5025
4800// private void CheckHeartbeat() 5026 private void CheckHeartbeat()
4801// { 5027 {
4802// if (m_firstHeartbeat) 5028 if (m_firstHeartbeat)
4803// return; 5029 return;
4804// 5030
4805// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5031 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
4806// StartTimer(); 5032 Start();
4807// } 5033 }
4808 5034
4809 public override ISceneObject DeserializeObject(string representation) 5035 public override ISceneObject DeserializeObject(string representation)
4810 { 5036 {
@@ -4816,9 +5042,14 @@ namespace OpenSim.Region.Framework.Scenes
4816 get { return m_allowScriptCrossings; } 5042 get { return m_allowScriptCrossings; }
4817 } 5043 }
4818 5044
4819 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 5045 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
5046 {
5047 return GetNearestAllowedPosition(avatar, null);
5048 }
5049
5050 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
4820 { 5051 {
4821 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 5052 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4822 5053
4823 if (nearestParcel != null) 5054 if (nearestParcel != null)
4824 { 5055 {
@@ -4827,10 +5058,7 @@ namespace OpenSim.Region.Framework.Scenes
4827 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5058 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4828 if (nearestPoint != null) 5059 if (nearestPoint != null)
4829 { 5060 {
4830// m_log.DebugFormat( 5061 Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
4831// "[SCENE]: Found a sane previous position based on velocity for {0}, sending them to {1} in {2}",
4832// avatar.Name, nearestPoint, nearestParcel.LandData.Name);
4833
4834 return nearestPoint.Value; 5062 return nearestPoint.Value;
4835 } 5063 }
4836 5064
@@ -4840,17 +5068,20 @@ namespace OpenSim.Region.Framework.Scenes
4840 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5068 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4841 if (nearestPoint != null) 5069 if (nearestPoint != null)
4842 { 5070 {
4843// m_log.DebugFormat( 5071 Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString());
4844// "[SCENE]: {0} had a zero velocity, sending them to {1}", avatar.Name, nearestPoint);
4845
4846 return nearestPoint.Value; 5072 return nearestPoint.Value;
4847 } 5073 }
4848 5074
4849 //Ultimate backup if we have no idea where they are 5075 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
4850// m_log.DebugFormat( 5076 if (dest != excludeParcel)
4851// "[SCENE]: No idea where {0} is, sending them to {1}", avatar.Name, avatar.lastKnownAllowedPosition); 5077 {
5078 // Ultimate backup if we have no idea where they are and
5079 // the last allowed position was in another parcel
5080 Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
5081 return avatar.lastKnownAllowedPosition;
5082 }
4852 5083
4853 return avatar.lastKnownAllowedPosition; 5084 // else fall through to region edge
4854 } 5085 }
4855 5086
4856 //Go to the edge, this happens in teleporting to a region with no available parcels 5087 //Go to the edge, this happens in teleporting to a region with no available parcels
@@ -4884,13 +5115,18 @@ namespace OpenSim.Region.Framework.Scenes
4884 5115
4885 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 5116 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4886 { 5117 {
5118 return GetNearestAllowedParcel(avatarId, x, y, null);
5119 }
5120
5121 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
5122 {
4887 List<ILandObject> all = AllParcels(); 5123 List<ILandObject> all = AllParcels();
4888 float minParcelDistance = float.MaxValue; 5124 float minParcelDistance = float.MaxValue;
4889 ILandObject nearestParcel = null; 5125 ILandObject nearestParcel = null;
4890 5126
4891 foreach (var parcel in all) 5127 foreach (var parcel in all)
4892 { 5128 {
4893 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 5129 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4894 { 5130 {
4895 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 5131 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4896 if (parcelDistance < minParcelDistance) 5132 if (parcelDistance < minParcelDistance)
@@ -5132,7 +5368,55 @@ namespace OpenSim.Region.Framework.Scenes
5132 mapModule.GenerateMaptile(); 5368 mapModule.GenerateMaptile();
5133 } 5369 }
5134 5370
5135 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5371// public void CleanDroppedAttachments()
5372// {
5373// List<SceneObjectGroup> objectsToDelete =
5374// new List<SceneObjectGroup>();
5375//
5376// lock (m_cleaningAttachments)
5377// {
5378// ForEachSOG(delegate (SceneObjectGroup grp)
5379// {
5380// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5381// {
5382// UUID agentID = grp.OwnerID;
5383// if (agentID == UUID.Zero)
5384// {
5385// objectsToDelete.Add(grp);
5386// return;
5387// }
5388//
5389// ScenePresence sp = GetScenePresence(agentID);
5390// if (sp == null)
5391// {
5392// objectsToDelete.Add(grp);
5393// return;
5394// }
5395// }
5396// });
5397// }
5398//
5399// foreach (SceneObjectGroup grp in objectsToDelete)
5400// {
5401// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5402// DeleteSceneObject(grp, true);
5403// }
5404// }
5405
5406 public void ThreadAlive(int threadCode)
5407 {
5408 switch(threadCode)
5409 {
5410 case 1: // Incoming
5411 m_lastIncoming = Util.EnvironmentTickCount();
5412 break;
5413 case 2: // Incoming
5414 m_lastOutgoing = Util.EnvironmentTickCount();
5415 break;
5416 }
5417 }
5418
5419 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5136 { 5420 {
5137 RegenerateMaptile(); 5421 RegenerateMaptile();
5138 5422
@@ -5151,6 +5435,14 @@ namespace OpenSim.Region.Framework.Scenes
5151 // child agent creation, thereby emulating the SL behavior. 5435 // child agent creation, thereby emulating the SL behavior.
5152 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5436 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5153 { 5437 {
5438 reason = "You are banned from the region";
5439
5440 if (Permissions.IsGod(agentID))
5441 {
5442 reason = String.Empty;
5443 return true;
5444 }
5445
5154 int num = m_sceneGraph.GetNumberOfScenePresences(); 5446 int num = m_sceneGraph.GetNumberOfScenePresences();
5155 5447
5156 if (num >= RegionInfo.RegionSettings.AgentLimit) 5448 if (num >= RegionInfo.RegionSettings.AgentLimit)
@@ -5162,6 +5454,41 @@ namespace OpenSim.Region.Framework.Scenes
5162 } 5454 }
5163 } 5455 }
5164 5456
5457 ScenePresence presence = GetScenePresence(agentID);
5458 IClientAPI client = null;
5459 AgentCircuitData aCircuit = null;
5460
5461 if (presence != null)
5462 {
5463 client = presence.ControllingClient;
5464 if (client != null)
5465 aCircuit = client.RequestClientInfo();
5466 }
5467
5468 // We may be called before there is a presence or a client.
5469 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5470 if (client == null)
5471 {
5472 aCircuit = new AgentCircuitData();
5473 aCircuit.AgentID = agentID;
5474 aCircuit.firstname = String.Empty;
5475 aCircuit.lastname = String.Empty;
5476 }
5477
5478 try
5479 {
5480 if (!AuthorizeUser(aCircuit, out reason))
5481 {
5482 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5483 return false;
5484 }
5485 }
5486 catch (Exception e)
5487 {
5488 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5489 return false;
5490 }
5491
5165 if (position == Vector3.Zero) // Teleport 5492 if (position == Vector3.Zero) // Teleport
5166 { 5493 {
5167 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5494 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5190,13 +5517,46 @@ namespace OpenSim.Region.Framework.Scenes
5190 } 5517 }
5191 } 5518 }
5192 } 5519 }
5520
5521 float posX = 128.0f;
5522 float posY = 128.0f;
5523
5524 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5525 {
5526 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5527 return false;
5528 }
5529 }
5530 else // Walking
5531 {
5532 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5533 if (land == null)
5534 return false;
5535
5536 bool banned = land.IsBannedFromLand(agentID);
5537 bool restricted = land.IsRestrictedFromLand(agentID);
5538
5539 if (banned || restricted)
5540 return false;
5193 } 5541 }
5194 5542
5195 reason = String.Empty; 5543 reason = String.Empty;
5196 return true; 5544 return true;
5197 } 5545 }
5198 5546
5199 /// <summary> 5547 public void StartTimerWatchdog()
5548 {
5549 m_timerWatchdog.Interval = 1000;
5550 m_timerWatchdog.Elapsed += TimerWatchdog;
5551 m_timerWatchdog.AutoReset = true;
5552 m_timerWatchdog.Start();
5553 }
5554
5555 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5556 {
5557 CheckHeartbeat();
5558 }
5559
5200 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5560 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5201 /// autopilot that moves an avatar to a sit target!. 5561 /// autopilot that moves an avatar to a sit target!.
5202 /// </summary> 5562 /// </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 0098add..cd4bd42 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();
@@ -337,6 +379,11 @@ namespace OpenSim.Region.Framework.Scenes
337 /// </returns> 379 /// </returns>
338 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 380 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
339 { 381 {
382 if (sceneObject == null)
383 {
384 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
385 return false;
386 }
340 if (sceneObject.UUID == UUID.Zero) 387 if (sceneObject.UUID == UUID.Zero)
341 { 388 {
342 m_log.ErrorFormat( 389 m_log.ErrorFormat(
@@ -471,6 +518,30 @@ namespace OpenSim.Region.Framework.Scenes
471 m_updateList[obj.UUID] = obj; 518 m_updateList[obj.UUID] = obj;
472 } 519 }
473 520
521 public void FireAttachToBackup(SceneObjectGroup obj)
522 {
523 if (OnAttachToBackup != null)
524 {
525 OnAttachToBackup(obj);
526 }
527 }
528
529 public void FireDetachFromBackup(SceneObjectGroup obj)
530 {
531 if (OnDetachFromBackup != null)
532 {
533 OnDetachFromBackup(obj);
534 }
535 }
536
537 public void FireChangeBackup(SceneObjectGroup obj)
538 {
539 if (OnChangeBackup != null)
540 {
541 OnChangeBackup(obj);
542 }
543 }
544
474 /// <summary> 545 /// <summary>
475 /// Process all pending updates 546 /// Process all pending updates
476 /// </summary> 547 /// </summary>
@@ -588,7 +659,8 @@ namespace OpenSim.Region.Framework.Scenes
588 659
589 Entities[presence.UUID] = presence; 660 Entities[presence.UUID] = presence;
590 661
591 lock (m_presenceLock) 662 m_scenePresencesLock.EnterWriteLock();
663 try
592 { 664 {
593 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 665 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
594 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 666 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -612,6 +684,10 @@ namespace OpenSim.Region.Framework.Scenes
612 m_scenePresenceMap = newmap; 684 m_scenePresenceMap = newmap;
613 m_scenePresenceArray = newlist; 685 m_scenePresenceArray = newlist;
614 } 686 }
687 finally
688 {
689 m_scenePresencesLock.ExitWriteLock();
690 }
615 } 691 }
616 692
617 /// <summary> 693 /// <summary>
@@ -626,7 +702,8 @@ namespace OpenSim.Region.Framework.Scenes
626 agentID); 702 agentID);
627 } 703 }
628 704
629 lock (m_presenceLock) 705 m_scenePresencesLock.EnterWriteLock();
706 try
630 { 707 {
631 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 708 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
632 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 709 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -648,6 +725,10 @@ namespace OpenSim.Region.Framework.Scenes
648 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 725 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
649 } 726 }
650 } 727 }
728 finally
729 {
730 m_scenePresencesLock.ExitWriteLock();
731 }
651 } 732 }
652 733
653 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 734 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1180,6 +1261,25 @@ namespace OpenSim.Region.Framework.Scenes
1180 1261
1181 #region Client Event handlers 1262 #region Client Event handlers
1182 1263
1264 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1265 {
1266 SceneObjectPart part = GetSceneObjectPart(localID);
1267 ObjectChangeData data = (ObjectChangeData)odata;
1268
1269 if (part != null)
1270 {
1271 SceneObjectGroup grp = part.ParentGroup;
1272 if (grp != null)
1273 {
1274 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1275 {
1276 part.StoreUndoState(data.change); // lets test only saving what we changed
1277 grp.doChangeObject(part, (ObjectChangeData)data);
1278 }
1279 }
1280 }
1281 }
1282
1183 /// <summary> 1283 /// <summary>
1184 /// Update the scale of an individual prim. 1284 /// Update the scale of an individual prim.
1185 /// </summary> 1285 /// </summary>
@@ -1194,7 +1294,17 @@ namespace OpenSim.Region.Framework.Scenes
1194 { 1294 {
1195 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1295 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1196 { 1296 {
1297 bool physbuild = false;
1298 if (part.ParentGroup.RootPart.PhysActor != null)
1299 {
1300 part.ParentGroup.RootPart.PhysActor.Building = true;
1301 physbuild = true;
1302 }
1303
1197 part.Resize(scale); 1304 part.Resize(scale);
1305
1306 if (physbuild)
1307 part.ParentGroup.RootPart.PhysActor.Building = false;
1198 } 1308 }
1199 } 1309 }
1200 } 1310 }
@@ -1206,7 +1316,17 @@ namespace OpenSim.Region.Framework.Scenes
1206 { 1316 {
1207 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1317 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1208 { 1318 {
1319 bool physbuild = false;
1320 if (group.RootPart.PhysActor != null)
1321 {
1322 group.RootPart.PhysActor.Building = true;
1323 physbuild = true;
1324 }
1325
1209 group.GroupResize(scale); 1326 group.GroupResize(scale);
1327
1328 if (physbuild)
1329 group.RootPart.PhysActor.Building = false;
1210 } 1330 }
1211 } 1331 }
1212 } 1332 }
@@ -1334,8 +1454,13 @@ namespace OpenSim.Region.Framework.Scenes
1334 { 1454 {
1335 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1455 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1336 { 1456 {
1337 if (m_parentScene.AttachmentsModule != null) 1457 // Set the new attachment point data in the object
1338 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1458 byte attachmentPoint = group.GetAttachmentPoint();
1459 group.UpdateGroupPosition(pos);
1460 group.IsAttachment = false;
1461 group.AbsolutePosition = group.RootPart.AttachedPos;
1462 group.AttachmentPoint = attachmentPoint;
1463 group.HasGroupChanged = true;
1339 } 1464 }
1340 else 1465 else
1341 { 1466 {
@@ -1383,7 +1508,7 @@ namespace OpenSim.Region.Framework.Scenes
1383 /// <param name="SetPhantom"></param> 1508 /// <param name="SetPhantom"></param>
1384 /// <param name="remoteClient"></param> 1509 /// <param name="remoteClient"></param>
1385 protected internal void UpdatePrimFlags( 1510 protected internal void UpdatePrimFlags(
1386 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) 1511 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient)
1387 { 1512 {
1388 SceneObjectGroup group = GetGroupByPrim(localID); 1513 SceneObjectGroup group = GetGroupByPrim(localID);
1389 if (group != null) 1514 if (group != null)
@@ -1391,7 +1516,18 @@ namespace OpenSim.Region.Framework.Scenes
1391 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1516 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1392 { 1517 {
1393 // VolumeDetect can't be set via UI and will always be off when a change is made there 1518 // VolumeDetect can't be set via UI and will always be off when a change is made there
1394 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); 1519 if (PhysData.PhysShapeType == PhysShapeType.invalid)
1520 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false);
1521 else
1522 {
1523 SceneObjectPart part = GetSceneObjectPart(localID);
1524 if (part != null)
1525 {
1526 part.UpdateExtraPhysics(PhysData);
1527 if (part.UpdatePhysRequired)
1528 remoteClient.SendPartPhysicsProprieties(part);
1529 }
1530 }
1395 } 1531 }
1396 } 1532 }
1397 } 1533 }
@@ -1535,6 +1671,7 @@ namespace OpenSim.Region.Framework.Scenes
1535 { 1671 {
1536 part.Material = Convert.ToByte(material); 1672 part.Material = Convert.ToByte(material);
1537 group.HasGroupChanged = true; 1673 group.HasGroupChanged = true;
1674 remoteClient.SendPartPhysicsProprieties(part);
1538 } 1675 }
1539 } 1676 }
1540 } 1677 }
@@ -1599,6 +1736,12 @@ namespace OpenSim.Region.Framework.Scenes
1599 /// <param name="childPrims"></param> 1736 /// <param name="childPrims"></param>
1600 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1737 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1601 { 1738 {
1739 if (root.KeyframeMotion != null)
1740 {
1741 root.KeyframeMotion.Stop();
1742 root.KeyframeMotion = null;
1743 }
1744
1602 SceneObjectGroup parentGroup = root.ParentGroup; 1745 SceneObjectGroup parentGroup = root.ParentGroup;
1603 if (parentGroup == null) return; 1746 if (parentGroup == null) return;
1604 1747
@@ -1607,8 +1750,11 @@ namespace OpenSim.Region.Framework.Scenes
1607 return; 1750 return;
1608 1751
1609 Monitor.Enter(m_updateLock); 1752 Monitor.Enter(m_updateLock);
1753
1610 try 1754 try
1611 { 1755 {
1756 parentGroup.areUpdatesSuspended = true;
1757
1612 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1758 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1613 1759
1614 // We do this in reverse to get the link order of the prims correct 1760 // We do this in reverse to get the link order of the prims correct
@@ -1623,9 +1769,13 @@ namespace OpenSim.Region.Framework.Scenes
1623 // Make sure no child prim is set for sale 1769 // Make sure no child prim is set for sale
1624 // So that, on delink, no prims are unwittingly 1770 // So that, on delink, no prims are unwittingly
1625 // left for sale and sold off 1771 // left for sale and sold off
1626 child.RootPart.ObjectSaleType = 0; 1772
1627 child.RootPart.SalePrice = 10; 1773 if (child != null)
1628 childGroups.Add(child); 1774 {
1775 child.RootPart.ObjectSaleType = 0;
1776 child.RootPart.SalePrice = 10;
1777 childGroups.Add(child);
1778 }
1629 } 1779 }
1630 1780
1631 foreach (SceneObjectGroup child in childGroups) 1781 foreach (SceneObjectGroup child in childGroups)
@@ -1652,6 +1802,16 @@ namespace OpenSim.Region.Framework.Scenes
1652 } 1802 }
1653 finally 1803 finally
1654 { 1804 {
1805 lock (SceneObjectGroupsByLocalPartID)
1806 {
1807 foreach (SceneObjectPart part in parentGroup.Parts)
1808 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1809 }
1810
1811 parentGroup.areUpdatesSuspended = false;
1812 parentGroup.HasGroupChanged = true;
1813 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1814 parentGroup.ScheduleGroupForFullUpdate();
1655 Monitor.Exit(m_updateLock); 1815 Monitor.Exit(m_updateLock);
1656 } 1816 }
1657 } 1817 }
@@ -1674,6 +1834,11 @@ namespace OpenSim.Region.Framework.Scenes
1674 { 1834 {
1675 if (part != null) 1835 if (part != null)
1676 { 1836 {
1837 if (part.KeyframeMotion != null)
1838 {
1839 part.KeyframeMotion.Stop();
1840 part.KeyframeMotion = null;
1841 }
1677 if (part.ParentGroup.PrimCount != 1) // Skip single 1842 if (part.ParentGroup.PrimCount != 1) // Skip single
1678 { 1843 {
1679 if (part.LinkNum < 2) // Root 1844 if (part.LinkNum < 2) // Root
@@ -1688,21 +1853,24 @@ namespace OpenSim.Region.Framework.Scenes
1688 1853
1689 SceneObjectGroup group = part.ParentGroup; 1854 SceneObjectGroup group = part.ParentGroup;
1690 if (!affectedGroups.Contains(group)) 1855 if (!affectedGroups.Contains(group))
1856 {
1857 group.areUpdatesSuspended = true;
1691 affectedGroups.Add(group); 1858 affectedGroups.Add(group);
1859 }
1692 } 1860 }
1693 } 1861 }
1694 } 1862 }
1695 1863
1696 foreach (SceneObjectPart child in childParts) 1864 if (childParts.Count > 0)
1697 { 1865 {
1698 // Unlink all child parts from their groups 1866 foreach (SceneObjectPart child in childParts)
1699 // 1867 {
1700 child.ParentGroup.DelinkFromGroup(child, true); 1868 // Unlink all child parts from their groups
1701 1869 //
1702 // These are not in affected groups and will not be 1870 child.ParentGroup.DelinkFromGroup(child, true);
1703 // handled further. Do the honors here. 1871 child.ParentGroup.HasGroupChanged = true;
1704 child.ParentGroup.HasGroupChanged = true; 1872 child.ParentGroup.ScheduleGroupForFullUpdate();
1705 child.ParentGroup.ScheduleGroupForFullUpdate(); 1873 }
1706 } 1874 }
1707 1875
1708 foreach (SceneObjectPart root in rootParts) 1876 foreach (SceneObjectPart root in rootParts)
@@ -1712,56 +1880,68 @@ namespace OpenSim.Region.Framework.Scenes
1712 // However, editing linked parts and unlinking may be different 1880 // However, editing linked parts and unlinking may be different
1713 // 1881 //
1714 SceneObjectGroup group = root.ParentGroup; 1882 SceneObjectGroup group = root.ParentGroup;
1883 group.areUpdatesSuspended = true;
1715 1884
1716 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1885 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1717 int numChildren = newSet.Count; 1886 int numChildren = newSet.Count;
1718 1887
1888 if (numChildren == 1)
1889 break;
1890
1719 // If there are prims left in a link set, but the root is 1891 // If there are prims left in a link set, but the root is
1720 // slated for unlink, we need to do this 1892 // slated for unlink, we need to do this
1893 // Unlink the remaining set
1721 // 1894 //
1722 if (numChildren != 1) 1895 bool sendEventsToRemainder = true;
1723 { 1896 if (numChildren > 1)
1724 // Unlink the remaining set 1897 sendEventsToRemainder = false;
1725 //
1726 bool sendEventsToRemainder = true;
1727 if (numChildren > 1)
1728 sendEventsToRemainder = false;
1729 1898
1730 foreach (SceneObjectPart p in newSet) 1899 foreach (SceneObjectPart p in newSet)
1900 {
1901 if (p != group.RootPart)
1731 { 1902 {
1732 if (p != group.RootPart) 1903 group.DelinkFromGroup(p, sendEventsToRemainder);
1733 group.DelinkFromGroup(p, sendEventsToRemainder); 1904 if (numChildren > 2)
1905 {
1906 p.ParentGroup.areUpdatesSuspended = true;
1907 }
1908 else
1909 {
1910 p.ParentGroup.HasGroupChanged = true;
1911 p.ParentGroup.ScheduleGroupForFullUpdate();
1912 }
1734 } 1913 }
1914 }
1915
1916 // If there is more than one prim remaining, we
1917 // need to re-link
1918 //
1919 if (numChildren > 2)
1920 {
1921 // Remove old root
1922 //
1923 if (newSet.Contains(root))
1924 newSet.Remove(root);
1735 1925
1736 // If there is more than one prim remaining, we 1926 // Preserve link ordering
1737 // need to re-link
1738 // 1927 //
1739 if (numChildren > 2) 1928 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1740 { 1929 {
1741 // Remove old root 1930 return a.LinkNum.CompareTo(b.LinkNum);
1742 // 1931 });
1743 if (newSet.Contains(root))
1744 newSet.Remove(root);
1745
1746 // Preserve link ordering
1747 //
1748 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1749 {
1750 return a.LinkNum.CompareTo(b.LinkNum);
1751 });
1752 1932
1753 // Determine new root 1933 // Determine new root
1754 // 1934 //
1755 SceneObjectPart newRoot = newSet[0]; 1935 SceneObjectPart newRoot = newSet[0];
1756 newSet.RemoveAt(0); 1936 newSet.RemoveAt(0);
1757 1937
1758 foreach (SceneObjectPart newChild in newSet) 1938 foreach (SceneObjectPart newChild in newSet)
1759 newChild.ClearUpdateSchedule(); 1939 newChild.ClearUpdateSchedule();
1760 1940
1761 LinkObjects(newRoot, newSet); 1941 newRoot.ParentGroup.areUpdatesSuspended = true;
1762 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1942 LinkObjects(newRoot, newSet);
1763 affectedGroups.Add(newRoot.ParentGroup); 1943 if (!affectedGroups.Contains(newRoot.ParentGroup))
1764 } 1944 affectedGroups.Add(newRoot.ParentGroup);
1765 } 1945 }
1766 } 1946 }
1767 1947
@@ -1769,8 +1949,14 @@ namespace OpenSim.Region.Framework.Scenes
1769 // 1949 //
1770 foreach (SceneObjectGroup g in affectedGroups) 1950 foreach (SceneObjectGroup g in affectedGroups)
1771 { 1951 {
1952 // Child prims that have been unlinked and deleted will
1953 // return unless the root is deleted. This will remove them
1954 // from the database. They will be rewritten immediately,
1955 // minus the rows for the unlinked child prims.
1956 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1772 g.TriggerScriptChangedEvent(Changed.LINK); 1957 g.TriggerScriptChangedEvent(Changed.LINK);
1773 g.HasGroupChanged = true; // Persist 1958 g.HasGroupChanged = true; // Persist
1959 g.areUpdatesSuspended = false;
1774 g.ScheduleGroupForFullUpdate(); 1960 g.ScheduleGroupForFullUpdate();
1775 } 1961 }
1776 } 1962 }
@@ -1872,9 +2058,6 @@ namespace OpenSim.Region.Framework.Scenes
1872 child.ApplyNextOwnerPermissions(); 2058 child.ApplyNextOwnerPermissions();
1873 } 2059 }
1874 } 2060 }
1875
1876 copy.RootPart.ObjectSaleType = 0;
1877 copy.RootPart.SalePrice = 10;
1878 } 2061 }
1879 2062
1880 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2063 // 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 10012d0..2effa25 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 87fdc41..5f33452 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; }
@@ -404,14 +478,99 @@ namespace OpenSim.Region.Framework.Scenes
404 478
405 if (Scene != null) 479 if (Scene != null)
406 { 480 {
407 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 481 // if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W)
408 || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S)) 482 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
483 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
484 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W)
485 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S))
409 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 486 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
410 { 487 {
411 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 488 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
489 uint x = 0;
490 uint y = 0;
491 string version = String.Empty;
492 Vector3 newpos = Vector3.Zero;
493 OpenSim.Services.Interfaces.GridRegion destination = null;
494
495 bool canCross = true;
496 foreach (ScenePresence av in m_linkedAvatars)
497 {
498 // We need to cross these agents. First, let's find
499 // out if any of them can't cross for some reason.
500 // We have to deny the crossing entirely if any
501 // of them are banned. Alternatively, we could
502 // unsit banned agents....
503
504
505 // We set the avatar position as being the object
506 // position to get the region to send to
507 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
508 {
509 canCross = false;
510 break;
511 }
512
513 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
514 }
515
516 if (canCross)
517 {
518 // We unparent the SP quietly so that it won't
519 // be made to stand up
520 foreach (ScenePresence av in m_linkedAvatars)
521 {
522 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
523 if (parentPart != null)
524 av.ParentUUID = parentPart.UUID;
525
526 av.ParentID = 0;
527 }
528
529 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
530
531 // Normalize
532 if (val.X >= Constants.RegionSize)
533 val.X -= Constants.RegionSize;
534 if (val.Y >= Constants.RegionSize)
535 val.Y -= Constants.RegionSize;
536 if (val.X < 0)
537 val.X += Constants.RegionSize;
538 if (val.Y < 0)
539 val.Y += Constants.RegionSize;
540
541 // If it's deleted, crossing was successful
542 if (IsDeleted)
543 {
544 foreach (ScenePresence av in m_linkedAvatars)
545 {
546 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
547
548 av.IsInTransit = true;
549
550 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
551 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
552 }
553
554 return;
555 }
556 }
557 else if (RootPart.PhysActor != null)
558 {
559 RootPart.PhysActor.CrossingFailure();
560 }
561
562 Vector3 oldp = AbsolutePosition;
563 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
564 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
565 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
412 } 566 }
413 } 567 }
414 568/* don't see the need but worse don't see where is restored to false if things stay in
569 foreach (SceneObjectPart part in m_parts.GetArray())
570 {
571 part.IgnoreUndoUpdate = true;
572 }
573 */
415 if (RootPart.GetStatusSandbox()) 574 if (RootPart.GetStatusSandbox())
416 { 575 {
417 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 576 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -425,10 +584,30 @@ namespace OpenSim.Region.Framework.Scenes
425 return; 584 return;
426 } 585 }
427 } 586 }
428
429 SceneObjectPart[] parts = m_parts.GetArray(); 587 SceneObjectPart[] parts = m_parts.GetArray();
430 for (int i = 0; i < parts.Length; i++) 588 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
431 parts[i].GroupPosition = val; 589 if (m_dupeInProgress)
590 triggerScriptEvent = false;
591 foreach (SceneObjectPart part in parts)
592 {
593 part.GroupPosition = val;
594 if (triggerScriptEvent)
595 part.TriggerScriptChangedEvent(Changed.POSITION);
596 }
597 if (!m_dupeInProgress)
598 {
599 foreach (ScenePresence av in m_linkedAvatars)
600 {
601 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
602 if (p != null && m_parts.TryGetValue(p.UUID, out p))
603 {
604 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
605 av.AbsolutePosition += offset;
606 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
607 av.SendAvatarDataToAllAgents();
608 }
609 }
610 }
432 611
433 //if (m_rootPart.PhysActor != null) 612 //if (m_rootPart.PhysActor != null)
434 //{ 613 //{
@@ -443,6 +622,29 @@ namespace OpenSim.Region.Framework.Scenes
443 } 622 }
444 } 623 }
445 624
625 public override Vector3 Velocity
626 {
627 get { return RootPart.Velocity; }
628 set { RootPart.Velocity = value; }
629 }
630
631 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
632 {
633 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
634 ScenePresence agent = icon.EndInvoke(iar);
635
636 //// If the cross was successful, this agent is a child agent
637 //if (agent.IsChildAgent)
638 // agent.Reset();
639 //else // Not successful
640 // agent.RestoreInCurrentScene();
641
642 // In any case
643 agent.IsInTransit = false;
644
645 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
646 }
647
446 public override uint LocalId 648 public override uint LocalId
447 { 649 {
448 get { return m_rootPart.LocalId; } 650 get { return m_rootPart.LocalId; }
@@ -540,6 +742,8 @@ namespace OpenSim.Region.Framework.Scenes
540 childPa.Selected = value; 742 childPa.Selected = value;
541 } 743 }
542 } 744 }
745 if (RootPart.KeyframeMotion != null)
746 RootPart.KeyframeMotion.Selected = value;
543 } 747 }
544 } 748 }
545 749
@@ -599,6 +803,7 @@ namespace OpenSim.Region.Framework.Scenes
599 /// </summary> 803 /// </summary>
600 public SceneObjectGroup() 804 public SceneObjectGroup()
601 { 805 {
806
602 } 807 }
603 808
604 /// <summary> 809 /// <summary>
@@ -615,7 +820,7 @@ namespace OpenSim.Region.Framework.Scenes
615 /// Constructor. This object is added to the scene later via AttachToScene() 820 /// Constructor. This object is added to the scene later via AttachToScene()
616 /// </summary> 821 /// </summary>
617 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 822 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
618 { 823 {
619 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 824 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
620 } 825 }
621 826
@@ -663,6 +868,9 @@ namespace OpenSim.Region.Framework.Scenes
663 /// </summary> 868 /// </summary>
664 public virtual void AttachToBackup() 869 public virtual void AttachToBackup()
665 { 870 {
871 if (IsAttachment) return;
872 m_scene.SceneGraph.FireAttachToBackup(this);
873
666 if (InSceneBackup) 874 if (InSceneBackup)
667 { 875 {
668 //m_log.DebugFormat( 876 //m_log.DebugFormat(
@@ -705,6 +913,13 @@ namespace OpenSim.Region.Framework.Scenes
705 913
706 ApplyPhysics(); 914 ApplyPhysics();
707 915
916 if (RootPart.PhysActor != null)
917 RootPart.Force = RootPart.Force;
918 if (RootPart.PhysActor != null)
919 RootPart.Torque = RootPart.Torque;
920 if (RootPart.PhysActor != null)
921 RootPart.Buoyancy = RootPart.Buoyancy;
922
708 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 923 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
709 // for the same object with very different properties. The caller must schedule the update. 924 // for the same object with very different properties. The caller must schedule the update.
710 //ScheduleGroupForFullUpdate(); 925 //ScheduleGroupForFullUpdate();
@@ -720,6 +935,10 @@ namespace OpenSim.Region.Framework.Scenes
720 EntityIntersection result = new EntityIntersection(); 935 EntityIntersection result = new EntityIntersection();
721 936
722 SceneObjectPart[] parts = m_parts.GetArray(); 937 SceneObjectPart[] parts = m_parts.GetArray();
938
939 // Find closest hit here
940 float idist = float.MaxValue;
941
723 for (int i = 0; i < parts.Length; i++) 942 for (int i = 0; i < parts.Length; i++)
724 { 943 {
725 SceneObjectPart part = parts[i]; 944 SceneObjectPart part = parts[i];
@@ -734,11 +953,6 @@ namespace OpenSim.Region.Framework.Scenes
734 953
735 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 954 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
736 955
737 // This may need to be updated to the maximum draw distance possible..
738 // We might (and probably will) be checking for prim creation from other sims
739 // when the camera crosses the border.
740 float idist = Constants.RegionSize;
741
742 if (inter.HitTF) 956 if (inter.HitTF)
743 { 957 {
744 // We need to find the closest prim to return to the testcaller along the ray 958 // We need to find the closest prim to return to the testcaller along the ray
@@ -749,10 +963,11 @@ namespace OpenSim.Region.Framework.Scenes
749 result.obj = part; 963 result.obj = part;
750 result.normal = inter.normal; 964 result.normal = inter.normal;
751 result.distance = inter.distance; 965 result.distance = inter.distance;
966
967 idist = inter.distance;
752 } 968 }
753 } 969 }
754 } 970 }
755
756 return result; 971 return result;
757 } 972 }
758 973
@@ -764,25 +979,27 @@ namespace OpenSim.Region.Framework.Scenes
764 /// <returns></returns> 979 /// <returns></returns>
765 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 980 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
766 { 981 {
767 maxX = -256f; 982 maxX = float.MinValue;
768 maxY = -256f; 983 maxY = float.MinValue;
769 maxZ = -256f; 984 maxZ = float.MinValue;
770 minX = 256f; 985 minX = float.MaxValue;
771 minY = 256f; 986 minY = float.MaxValue;
772 minZ = 8192f; 987 minZ = float.MaxValue;
773 988
774 SceneObjectPart[] parts = m_parts.GetArray(); 989 SceneObjectPart[] parts = m_parts.GetArray();
775 for (int i = 0; i < parts.Length; i++) 990 foreach (SceneObjectPart part in parts)
776 { 991 {
777 SceneObjectPart part = parts[i];
778
779 Vector3 worldPos = part.GetWorldPosition(); 992 Vector3 worldPos = part.GetWorldPosition();
780 Vector3 offset = worldPos - AbsolutePosition; 993 Vector3 offset = worldPos - AbsolutePosition;
781 Quaternion worldRot; 994 Quaternion worldRot;
782 if (part.ParentID == 0) 995 if (part.ParentID == 0)
996 {
783 worldRot = part.RotationOffset; 997 worldRot = part.RotationOffset;
998 }
784 else 999 else
1000 {
785 worldRot = part.GetWorldRotation(); 1001 worldRot = part.GetWorldRotation();
1002 }
786 1003
787 Vector3 frontTopLeft; 1004 Vector3 frontTopLeft;
788 Vector3 frontTopRight; 1005 Vector3 frontTopRight;
@@ -794,6 +1011,8 @@ namespace OpenSim.Region.Framework.Scenes
794 Vector3 backBottomLeft; 1011 Vector3 backBottomLeft;
795 Vector3 backBottomRight; 1012 Vector3 backBottomRight;
796 1013
1014 // Vector3[] corners = new Vector3[8];
1015
797 Vector3 orig = Vector3.Zero; 1016 Vector3 orig = Vector3.Zero;
798 1017
799 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1018 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -828,6 +1047,38 @@ namespace OpenSim.Region.Framework.Scenes
828 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1047 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
829 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1048 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
830 1049
1050
1051
1052 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1053 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1054 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1055 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1056 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1057 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1058 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1059 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1060
1061 //for (int i = 0; i < 8; i++)
1062 //{
1063 // corners[i] = corners[i] * worldRot;
1064 // corners[i] += offset;
1065
1066 // if (corners[i].X > maxX)
1067 // maxX = corners[i].X;
1068 // if (corners[i].X < minX)
1069 // minX = corners[i].X;
1070
1071 // if (corners[i].Y > maxY)
1072 // maxY = corners[i].Y;
1073 // if (corners[i].Y < minY)
1074 // minY = corners[i].Y;
1075
1076 // if (corners[i].Z > maxZ)
1077 // maxZ = corners[i].Y;
1078 // if (corners[i].Z < minZ)
1079 // minZ = corners[i].Z;
1080 //}
1081
831 frontTopLeft = frontTopLeft * worldRot; 1082 frontTopLeft = frontTopLeft * worldRot;
832 frontTopRight = frontTopRight * worldRot; 1083 frontTopRight = frontTopRight * worldRot;
833 frontBottomLeft = frontBottomLeft * worldRot; 1084 frontBottomLeft = frontBottomLeft * worldRot;
@@ -849,6 +1100,15 @@ namespace OpenSim.Region.Framework.Scenes
849 backTopLeft += offset; 1100 backTopLeft += offset;
850 backTopRight += offset; 1101 backTopRight += offset;
851 1102
1103 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1104 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1105 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1106 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1107 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1108 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1109 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1110 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1111
852 if (frontTopRight.X > maxX) 1112 if (frontTopRight.X > maxX)
853 maxX = frontTopRight.X; 1113 maxX = frontTopRight.X;
854 if (frontTopLeft.X > maxX) 1114 if (frontTopLeft.X > maxX)
@@ -992,17 +1252,118 @@ namespace OpenSim.Region.Framework.Scenes
992 1252
993 #endregion 1253 #endregion
994 1254
1255 public void GetResourcesCosts(SceneObjectPart apart,
1256 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1257 {
1258 // this information may need to be cached
1259
1260 float cost;
1261 float tmpcost;
1262
1263 bool ComplexCost = false;
1264
1265 SceneObjectPart p;
1266 SceneObjectPart[] parts;
1267
1268 lock (m_parts)
1269 {
1270 parts = m_parts.GetArray();
1271 }
1272
1273 int nparts = parts.Length;
1274
1275
1276 for (int i = 0; i < nparts; i++)
1277 {
1278 p = parts[i];
1279
1280 if (p.UsesComplexCost)
1281 {
1282 ComplexCost = true;
1283 break;
1284 }
1285 }
1286
1287 if (ComplexCost)
1288 {
1289 linksetResCost = 0;
1290 linksetPhysCost = 0;
1291 partCost = 0;
1292 partPhysCost = 0;
1293
1294 for (int i = 0; i < nparts; i++)
1295 {
1296 p = parts[i];
1297
1298 cost = p.StreamingCost;
1299 tmpcost = p.SimulationCost;
1300 if (tmpcost > cost)
1301 cost = tmpcost;
1302 tmpcost = p.PhysicsCost;
1303 if (tmpcost > cost)
1304 cost = tmpcost;
1305
1306 linksetPhysCost += tmpcost;
1307 linksetResCost += cost;
1308
1309 if (p == apart)
1310 {
1311 partCost = cost;
1312 partPhysCost = tmpcost;
1313 }
1314 }
1315 }
1316 else
1317 {
1318 partPhysCost = 1.0f;
1319 partCost = 1.0f;
1320 linksetResCost = (float)nparts;
1321 linksetPhysCost = linksetResCost;
1322 }
1323 }
1324
1325 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1326 {
1327 SceneObjectPart p;
1328 SceneObjectPart[] parts;
1329
1330 lock (m_parts)
1331 {
1332 parts = m_parts.GetArray();
1333 }
1334
1335 int nparts = parts.Length;
1336
1337 PhysCost = 0;
1338 StreamCost = 0;
1339 SimulCost = 0;
1340
1341 for (int i = 0; i < nparts; i++)
1342 {
1343 p = parts[i];
1344
1345 StreamCost += p.StreamingCost;
1346 SimulCost += p.SimulationCost;
1347 PhysCost += p.PhysicsCost;
1348 }
1349 }
1350
995 public void SaveScriptedState(XmlTextWriter writer) 1351 public void SaveScriptedState(XmlTextWriter writer)
996 { 1352 {
1353 SaveScriptedState(writer, false);
1354 }
1355
1356 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1357 {
997 XmlDocument doc = new XmlDocument(); 1358 XmlDocument doc = new XmlDocument();
998 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1359 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
999 1360
1000 SceneObjectPart[] parts = m_parts.GetArray(); 1361 SceneObjectPart[] parts = m_parts.GetArray();
1001 for (int i = 0; i < parts.Length; i++) 1362 for (int i = 0; i < parts.Length; i++)
1002 { 1363 {
1003 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1364 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
1004 foreach (KeyValuePair<UUID, string> kvp in pstates) 1365 foreach (KeyValuePair<UUID, string> kvp in pstates)
1005 states.Add(kvp.Key, kvp.Value); 1366 states[kvp.Key] = kvp.Value;
1006 } 1367 }
1007 1368
1008 if (states.Count > 0) 1369 if (states.Count > 0)
@@ -1022,6 +1383,169 @@ namespace OpenSim.Region.Framework.Scenes
1022 } 1383 }
1023 1384
1024 /// <summary> 1385 /// <summary>
1386 /// Add the avatar to this linkset (avatar is sat).
1387 /// </summary>
1388 /// <param name="agentID"></param>
1389 public void AddAvatar(UUID agentID)
1390 {
1391 ScenePresence presence;
1392 if (m_scene.TryGetScenePresence(agentID, out presence))
1393 {
1394 if (!m_linkedAvatars.Contains(presence))
1395 {
1396 m_linkedAvatars.Add(presence);
1397 }
1398 }
1399 }
1400
1401 /// <summary>
1402 /// Delete the avatar from this linkset (avatar is unsat).
1403 /// </summary>
1404 /// <param name="agentID"></param>
1405 public void DeleteAvatar(UUID agentID)
1406 {
1407 ScenePresence presence;
1408 if (m_scene.TryGetScenePresence(agentID, out presence))
1409 {
1410 if (m_linkedAvatars.Contains(presence))
1411 {
1412 m_linkedAvatars.Remove(presence);
1413 }
1414 }
1415 }
1416
1417 /// <summary>
1418 /// Returns the list of linked presences (avatars sat on this group)
1419 /// </summary>
1420 /// <param name="agentID"></param>
1421 public List<ScenePresence> GetLinkedAvatars()
1422 {
1423 return m_linkedAvatars;
1424 }
1425
1426 /// <summary>
1427 /// Attach this scene object to the given avatar.
1428 /// </summary>
1429 /// <param name="agentID"></param>
1430 /// <param name="attachmentpoint"></param>
1431 /// <param name="AttachOffset"></param>
1432 private void AttachToAgent(
1433 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1434 {
1435 if (avatar != null)
1436 {
1437 // don't attach attachments to child agents
1438 if (avatar.IsChildAgent) return;
1439
1440 // Remove from database and parcel prim count
1441 m_scene.DeleteFromStorage(so.UUID);
1442 m_scene.EventManager.TriggerParcelPrimCountTainted();
1443
1444 so.AttachedAvatar = avatar.UUID;
1445
1446 if (so.RootPart.PhysActor != null)
1447 {
1448 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1449 so.RootPart.PhysActor = null;
1450 }
1451
1452 so.AbsolutePosition = attachOffset;
1453 so.RootPart.AttachedPos = attachOffset;
1454 so.IsAttachment = true;
1455 so.RootPart.SetParentLocalId(avatar.LocalId);
1456 so.AttachmentPoint = attachmentpoint;
1457
1458 avatar.AddAttachment(this);
1459
1460 if (!silent)
1461 {
1462 // Killing it here will cause the client to deselect it
1463 // It then reappears on the avatar, deselected
1464 // through the full update below
1465 //
1466 if (IsSelected)
1467 {
1468 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1469 }
1470
1471 IsSelected = false; // fudge....
1472 ScheduleGroupForFullUpdate();
1473 }
1474 }
1475 else
1476 {
1477 m_log.WarnFormat(
1478 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1479 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1480 }
1481 }
1482
1483 public byte GetAttachmentPoint()
1484 {
1485 return m_rootPart.Shape.State;
1486 }
1487
1488 public void DetachToGround()
1489 {
1490 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1491 if (avatar == null)
1492 return;
1493
1494 avatar.RemoveAttachment(this);
1495
1496 Vector3 detachedpos = new Vector3(127f,127f,127f);
1497 if (avatar == null)
1498 return;
1499
1500 detachedpos = avatar.AbsolutePosition;
1501 RootPart.FromItemID = UUID.Zero;
1502
1503 AbsolutePosition = detachedpos;
1504 AttachedAvatar = UUID.Zero;
1505
1506 //SceneObjectPart[] parts = m_parts.GetArray();
1507 //for (int i = 0; i < parts.Length; i++)
1508 // parts[i].AttachedAvatar = UUID.Zero;
1509
1510 m_rootPart.SetParentLocalId(0);
1511 AttachmentPoint = (byte)0;
1512 // must check if buildind should be true or false here
1513 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1514 HasGroupChanged = true;
1515 RootPart.Rezzed = DateTime.Now;
1516 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1517 AttachToBackup();
1518 m_scene.EventManager.TriggerParcelPrimCountTainted();
1519 m_rootPart.ScheduleFullUpdate();
1520 m_rootPart.ClearUndoState();
1521 }
1522
1523 public void DetachToInventoryPrep()
1524 {
1525 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1526 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1527 if (avatar != null)
1528 {
1529 //detachedpos = avatar.AbsolutePosition;
1530 avatar.RemoveAttachment(this);
1531 }
1532
1533 AttachedAvatar = UUID.Zero;
1534
1535 /*SceneObjectPart[] parts = m_parts.GetArray();
1536 for (int i = 0; i < parts.Length; i++)
1537 parts[i].AttachedAvatar = UUID.Zero;*/
1538
1539 m_rootPart.SetParentLocalId(0);
1540 //m_rootPart.SetAttachmentPoint((byte)0);
1541 IsAttachment = false;
1542 AbsolutePosition = m_rootPart.AttachedPos;
1543 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1544 //AttachToBackup();
1545 //m_rootPart.ScheduleFullUpdate();
1546 }
1547
1548 /// <summary>
1025 /// 1549 ///
1026 /// </summary> 1550 /// </summary>
1027 /// <param name="part"></param> 1551 /// <param name="part"></param>
@@ -1071,7 +1595,10 @@ namespace OpenSim.Region.Framework.Scenes
1071 public void AddPart(SceneObjectPart part) 1595 public void AddPart(SceneObjectPart part)
1072 { 1596 {
1073 part.SetParent(this); 1597 part.SetParent(this);
1074 part.LinkNum = m_parts.Add(part.UUID, part); 1598 m_parts.Add(part.UUID, part);
1599
1600 part.LinkNum = m_parts.Count;
1601
1075 if (part.LinkNum == 2) 1602 if (part.LinkNum == 2)
1076 RootPart.LinkNum = 1; 1603 RootPart.LinkNum = 1;
1077 } 1604 }
@@ -1159,7 +1686,7 @@ namespace OpenSim.Region.Framework.Scenes
1159// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1686// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1160// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1687// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1161 1688
1162 part.StoreUndoState(); 1689// part.StoreUndoState();
1163 part.OnGrab(offsetPos, remoteClient); 1690 part.OnGrab(offsetPos, remoteClient);
1164 } 1691 }
1165 1692
@@ -1179,6 +1706,11 @@ namespace OpenSim.Region.Framework.Scenes
1179 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1706 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1180 public void DeleteGroupFromScene(bool silent) 1707 public void DeleteGroupFromScene(bool silent)
1181 { 1708 {
1709 // We need to keep track of this state in case this group is still queued for backup.
1710 IsDeleted = true;
1711
1712 DetachFromBackup();
1713
1182 SceneObjectPart[] parts = m_parts.GetArray(); 1714 SceneObjectPart[] parts = m_parts.GetArray();
1183 for (int i = 0; i < parts.Length; i++) 1715 for (int i = 0; i < parts.Length; i++)
1184 { 1716 {
@@ -1201,6 +1733,8 @@ namespace OpenSim.Region.Framework.Scenes
1201 } 1733 }
1202 }); 1734 });
1203 } 1735 }
1736
1737
1204 } 1738 }
1205 1739
1206 public void AddScriptLPS(int count) 1740 public void AddScriptLPS(int count)
@@ -1270,28 +1804,43 @@ namespace OpenSim.Region.Framework.Scenes
1270 /// </summary> 1804 /// </summary>
1271 public void ApplyPhysics() 1805 public void ApplyPhysics()
1272 { 1806 {
1273 // Apply physics to the root prim
1274 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1275
1276 // Apply physics to child prims
1277 SceneObjectPart[] parts = m_parts.GetArray(); 1807 SceneObjectPart[] parts = m_parts.GetArray();
1278 if (parts.Length > 1) 1808 if (parts.Length > 1)
1279 { 1809 {
1810 ResetChildPrimPhysicsPositions();
1811
1812 // Apply physics to the root prim
1813 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
1814
1815
1280 for (int i = 0; i < parts.Length; i++) 1816 for (int i = 0; i < parts.Length; i++)
1281 { 1817 {
1282 SceneObjectPart part = parts[i]; 1818 SceneObjectPart part = parts[i];
1283 if (part.LocalId != m_rootPart.LocalId) 1819 if (part.LocalId != m_rootPart.LocalId)
1284 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 1820 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1285 } 1821 }
1286
1287 // Hack to get the physics scene geometries in the right spot 1822 // Hack to get the physics scene geometries in the right spot
1288 ResetChildPrimPhysicsPositions(); 1823// ResetChildPrimPhysicsPositions();
1824 if (m_rootPart.PhysActor != null)
1825 {
1826 m_rootPart.PhysActor.Building = false;
1827 }
1828 }
1829 else
1830 {
1831 // Apply physics to the root prim
1832 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1289 } 1833 }
1290 } 1834 }
1291 1835
1292 public void SetOwnerId(UUID userId) 1836 public void SetOwnerId(UUID userId)
1293 { 1837 {
1294 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1838 ForEachPart(delegate(SceneObjectPart part)
1839 {
1840
1841 part.OwnerID = userId;
1842
1843 });
1295 } 1844 }
1296 1845
1297 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1846 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1323,11 +1872,17 @@ namespace OpenSim.Region.Framework.Scenes
1323 return; 1872 return;
1324 } 1873 }
1325 1874
1875 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1876 return;
1877
1326 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1878 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1327 // any exception propogate upwards. 1879 // any exception propogate upwards.
1328 try 1880 try
1329 { 1881 {
1330 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1882 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1883 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1884 m_scene.LoadingPrims) // Land may not be valid yet
1885
1331 { 1886 {
1332 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1887 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1333 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1888 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1354,6 +1909,7 @@ namespace OpenSim.Region.Framework.Scenes
1354 } 1909 }
1355 } 1910 }
1356 } 1911 }
1912
1357 } 1913 }
1358 1914
1359 if (m_scene.UseBackup && HasGroupChanged) 1915 if (m_scene.UseBackup && HasGroupChanged)
@@ -1361,6 +1917,20 @@ namespace OpenSim.Region.Framework.Scenes
1361 // don't backup while it's selected or you're asking for changes mid stream. 1917 // don't backup while it's selected or you're asking for changes mid stream.
1362 if (isTimeToPersist() || forcedBackup) 1918 if (isTimeToPersist() || forcedBackup)
1363 { 1919 {
1920 if (m_rootPart.PhysActor != null &&
1921 (!m_rootPart.PhysActor.IsPhysical))
1922 {
1923 // Possible ghost prim
1924 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
1925 {
1926 foreach (SceneObjectPart part in m_parts.GetArray())
1927 {
1928 // Re-set physics actor positions and
1929 // orientations
1930 part.GroupPosition = m_rootPart.GroupPosition;
1931 }
1932 }
1933 }
1364// m_log.DebugFormat( 1934// m_log.DebugFormat(
1365// "[SCENE]: Storing {0}, {1} in {2}", 1935// "[SCENE]: Storing {0}, {1} in {2}",
1366// Name, UUID, m_scene.RegionInfo.RegionName); 1936// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -1378,6 +1948,11 @@ namespace OpenSim.Region.Framework.Scenes
1378 1948
1379 backup_group.ForEachPart(delegate(SceneObjectPart part) 1949 backup_group.ForEachPart(delegate(SceneObjectPart part)
1380 { 1950 {
1951 if (part.KeyframeMotion != null)
1952 {
1953 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
1954 part.KeyframeMotion.UpdateSceneObject(this);
1955 }
1381 part.Inventory.ProcessInventoryBackup(datastore); 1956 part.Inventory.ProcessInventoryBackup(datastore);
1382 }); 1957 });
1383 1958
@@ -1430,6 +2005,7 @@ namespace OpenSim.Region.Framework.Scenes
1430 /// <returns></returns> 2005 /// <returns></returns>
1431 public SceneObjectGroup Copy(bool userExposed) 2006 public SceneObjectGroup Copy(bool userExposed)
1432 { 2007 {
2008 m_dupeInProgress = true;
1433 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 2009 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1434 dupe.m_isBackedUp = false; 2010 dupe.m_isBackedUp = false;
1435 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2011 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
@@ -1444,7 +2020,7 @@ namespace OpenSim.Region.Framework.Scenes
1444 // This is only necessary when userExposed is false! 2020 // This is only necessary when userExposed is false!
1445 2021
1446 bool previousAttachmentStatus = dupe.IsAttachment; 2022 bool previousAttachmentStatus = dupe.IsAttachment;
1447 2023
1448 if (!userExposed) 2024 if (!userExposed)
1449 dupe.IsAttachment = true; 2025 dupe.IsAttachment = true;
1450 2026
@@ -1462,11 +2038,11 @@ namespace OpenSim.Region.Framework.Scenes
1462 dupe.m_rootPart.TrimPermissions(); 2038 dupe.m_rootPart.TrimPermissions();
1463 2039
1464 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2040 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1465 2041
1466 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2042 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1467 { 2043 {
1468 return p1.LinkNum.CompareTo(p2.LinkNum); 2044 return p1.LinkNum.CompareTo(p2.LinkNum);
1469 } 2045 }
1470 ); 2046 );
1471 2047
1472 foreach (SceneObjectPart part in partList) 2048 foreach (SceneObjectPart part in partList)
@@ -1476,41 +2052,53 @@ namespace OpenSim.Region.Framework.Scenes
1476 { 2052 {
1477 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2053 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1478 newPart.LinkNum = part.LinkNum; 2054 newPart.LinkNum = part.LinkNum;
1479 } 2055 if (userExposed)
2056 newPart.ParentID = dupe.m_rootPart.LocalId;
2057 }
1480 else 2058 else
1481 { 2059 {
1482 newPart = dupe.m_rootPart; 2060 newPart = dupe.m_rootPart;
1483 } 2061 }
2062/*
2063 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2064 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1484 2065
1485 // Need to duplicate the physics actor as well 2066 // Need to duplicate the physics actor as well
1486 PhysicsActor originalPartPa = part.PhysActor; 2067 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1487 if (originalPartPa != null && userExposed)
1488 { 2068 {
1489 PrimitiveBaseShape pbs = newPart.Shape; 2069 PrimitiveBaseShape pbs = newPart.Shape;
1490
1491 newPart.PhysActor 2070 newPart.PhysActor
1492 = m_scene.PhysicsScene.AddPrimShape( 2071 = m_scene.PhysicsScene.AddPrimShape(
1493 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2072 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1494 pbs, 2073 pbs,
1495 newPart.AbsolutePosition, 2074 newPart.AbsolutePosition,
1496 newPart.Scale, 2075 newPart.Scale,
1497 newPart.RotationOffset, 2076 newPart.GetWorldRotation(),
1498 originalPartPa.IsPhysical, 2077 isphys,
2078 isphan,
1499 newPart.LocalId); 2079 newPart.LocalId);
1500 2080
1501 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2081 newPart.DoPhysicsPropertyUpdate(isphys, true);
1502 } 2082 */
2083 if (userExposed)
2084 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2085// }
1503 } 2086 }
1504 2087
1505 if (userExposed) 2088 if (userExposed)
1506 { 2089 {
1507 dupe.UpdateParentIDs(); 2090// done above dupe.UpdateParentIDs();
2091
2092 if (dupe.m_rootPart.PhysActor != null)
2093 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2094
1508 dupe.HasGroupChanged = true; 2095 dupe.HasGroupChanged = true;
1509 dupe.AttachToBackup(); 2096 dupe.AttachToBackup();
1510 2097
1511 ScheduleGroupForFullUpdate(); 2098 ScheduleGroupForFullUpdate();
1512 } 2099 }
1513 2100
2101 m_dupeInProgress = false;
1514 return dupe; 2102 return dupe;
1515 } 2103 }
1516 2104
@@ -1522,11 +2110,24 @@ namespace OpenSim.Region.Framework.Scenes
1522 /// <param name="cGroupID"></param> 2110 /// <param name="cGroupID"></param>
1523 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2111 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1524 { 2112 {
1525 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2113 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
2114 // give newpart a new local ID lettng old part keep same
2115 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2116 newpart.LocalId = m_scene.AllocateLocalId();
2117
2118 SetRootPart(newpart);
2119 if (userExposed)
2120 RootPart.Velocity = Vector3.Zero; // In case source is moving
1526 } 2121 }
1527 2122
1528 public void ScriptSetPhysicsStatus(bool usePhysics) 2123 public void ScriptSetPhysicsStatus(bool usePhysics)
1529 { 2124 {
2125 if (usePhysics)
2126 {
2127 if (RootPart.KeyframeMotion != null)
2128 RootPart.KeyframeMotion.Stop();
2129 RootPart.KeyframeMotion = null;
2130 }
1530 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2131 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1531 } 2132 }
1532 2133
@@ -1580,20 +2181,6 @@ namespace OpenSim.Region.Framework.Scenes
1580 } 2181 }
1581 } 2182 }
1582 2183
1583 public void applyAngularImpulse(Vector3 impulse)
1584 {
1585 PhysicsActor pa = RootPart.PhysActor;
1586
1587 if (pa != null)
1588 {
1589 if (!IsAttachment)
1590 {
1591 pa.AddAngularForce(impulse, true);
1592 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1593 }
1594 }
1595 }
1596
1597 public void setAngularImpulse(Vector3 impulse) 2184 public void setAngularImpulse(Vector3 impulse)
1598 { 2185 {
1599 PhysicsActor pa = RootPart.PhysActor; 2186 PhysicsActor pa = RootPart.PhysActor;
@@ -1610,20 +2197,10 @@ namespace OpenSim.Region.Framework.Scenes
1610 2197
1611 public Vector3 GetTorque() 2198 public Vector3 GetTorque()
1612 { 2199 {
1613 PhysicsActor pa = RootPart.PhysActor; 2200 return RootPart.Torque;
1614
1615 if (pa != null)
1616 {
1617 if (!IsAttachment)
1618 {
1619 Vector3 torque = pa.Torque;
1620 return torque;
1621 }
1622 }
1623
1624 return Vector3.Zero;
1625 } 2201 }
1626 2202
2203 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1627 public void moveToTarget(Vector3 target, float tau) 2204 public void moveToTarget(Vector3 target, float tau)
1628 { 2205 {
1629 if (IsAttachment) 2206 if (IsAttachment)
@@ -1655,6 +2232,46 @@ namespace OpenSim.Region.Framework.Scenes
1655 pa.PIDActive = false; 2232 pa.PIDActive = false;
1656 } 2233 }
1657 2234
2235 public void rotLookAt(Quaternion target, float strength, float damping)
2236 {
2237 SceneObjectPart rootpart = m_rootPart;
2238 if (rootpart != null)
2239 {
2240 if (IsAttachment)
2241 {
2242 /*
2243 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2244 if (avatar != null)
2245 {
2246 Rotate the Av?
2247 } */
2248 }
2249 else
2250 {
2251 if (rootpart.PhysActor != null)
2252 { // APID must be implemented in your physics system for this to function.
2253 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2254 rootpart.PhysActor.APIDStrength = strength;
2255 rootpart.PhysActor.APIDDamping = damping;
2256 rootpart.PhysActor.APIDActive = true;
2257 }
2258 }
2259 }
2260 }
2261
2262 public void stopLookAt()
2263 {
2264 SceneObjectPart rootpart = m_rootPart;
2265 if (rootpart != null)
2266 {
2267 if (rootpart.PhysActor != null)
2268 { // APID must be implemented in your physics system for this to function.
2269 rootpart.PhysActor.APIDActive = false;
2270 }
2271 }
2272
2273 }
2274
1658 /// <summary> 2275 /// <summary>
1659 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2276 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1660 /// </summary> 2277 /// </summary>
@@ -1711,7 +2328,12 @@ namespace OpenSim.Region.Framework.Scenes
1711 /// <param name="cGroupID"></param> 2328 /// <param name="cGroupID"></param>
1712 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2329 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1713 { 2330 {
1714 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2331 // give new ID to the new part, letting old keep original
2332 // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2333 SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2334 newPart.LocalId = m_scene.AllocateLocalId();
2335 newPart.SetParent(this);
2336
1715 AddPart(newPart); 2337 AddPart(newPart);
1716 2338
1717 SetPartAsNonRoot(newPart); 2339 SetPartAsNonRoot(newPart);
@@ -1840,11 +2462,11 @@ namespace OpenSim.Region.Framework.Scenes
1840 /// Immediately send a full update for this scene object. 2462 /// Immediately send a full update for this scene object.
1841 /// </summary> 2463 /// </summary>
1842 public void SendGroupFullUpdate() 2464 public void SendGroupFullUpdate()
1843 { 2465 {
1844 if (IsDeleted) 2466 if (IsDeleted)
1845 return; 2467 return;
1846 2468
1847// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2469// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1848 2470
1849 RootPart.SendFullUpdateToAllClients(); 2471 RootPart.SendFullUpdateToAllClients();
1850 2472
@@ -1959,6 +2581,11 @@ namespace OpenSim.Region.Framework.Scenes
1959 /// <param name="objectGroup">The group of prims which should be linked to this group</param> 2581 /// <param name="objectGroup">The group of prims which should be linked to this group</param>
1960 public void LinkToGroup(SceneObjectGroup objectGroup) 2582 public void LinkToGroup(SceneObjectGroup objectGroup)
1961 { 2583 {
2584 LinkToGroup(objectGroup, false);
2585 }
2586
2587 public void LinkToGroup(SceneObjectGroup objectGroup, bool insert)
2588 {
1962// m_log.DebugFormat( 2589// m_log.DebugFormat(
1963// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}", 2590// "[SCENE OBJECT GROUP]: Linking group with root part {0}, {1} to group with root part {2}, {3}",
1964// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID); 2591// objectGroup.RootPart.Name, objectGroup.RootPart.UUID, RootPart.Name, RootPart.UUID);
@@ -1969,6 +2596,15 @@ namespace OpenSim.Region.Framework.Scenes
1969 2596
1970 SceneObjectPart linkPart = objectGroup.m_rootPart; 2597 SceneObjectPart linkPart = objectGroup.m_rootPart;
1971 2598
2599 if (m_rootPart.PhysActor != null)
2600 m_rootPart.PhysActor.Building = true;
2601 if (linkPart.PhysActor != null)
2602 linkPart.PhysActor.Building = true;
2603
2604 // physics flags from group to be applied to linked parts
2605 bool grpusephys = UsesPhysics;
2606 bool grptemporary = IsTemporary;
2607
1972 Vector3 oldGroupPosition = linkPart.GroupPosition; 2608 Vector3 oldGroupPosition = linkPart.GroupPosition;
1973 Quaternion oldRootRotation = linkPart.RotationOffset; 2609 Quaternion oldRootRotation = linkPart.RotationOffset;
1974 2610
@@ -1992,13 +2628,34 @@ namespace OpenSim.Region.Framework.Scenes
1992 2628
1993 lock (m_parts.SyncRoot) 2629 lock (m_parts.SyncRoot)
1994 { 2630 {
1995 int linkNum = PrimCount + 1; 2631 int linkNum;
2632 if (insert)
2633 {
2634 linkNum = 2;
2635 foreach (SceneObjectPart part in Parts)
2636 {
2637 if (part.LinkNum > 1)
2638 part.LinkNum++;
2639 }
2640 }
2641 else
2642 {
2643 linkNum = PrimCount + 1;
2644 }
1996 2645
1997 m_parts.Add(linkPart.UUID, linkPart); 2646 m_parts.Add(linkPart.UUID, linkPart);
1998 2647
1999 linkPart.SetParent(this); 2648 linkPart.SetParent(this);
2000 linkPart.CreateSelected = true; 2649 linkPart.CreateSelected = true;
2001 2650
2651 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2652 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2653 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2654 {
2655 linkPart.PhysActor.link(m_rootPart.PhysActor);
2656 this.Scene.PhysicsScene.AddPhysicsActorTaint(linkPart.PhysActor);
2657 }
2658
2002 linkPart.LinkNum = linkNum++; 2659 linkPart.LinkNum = linkNum++;
2003 2660
2004 SceneObjectPart[] ogParts = objectGroup.Parts; 2661 SceneObjectPart[] ogParts = objectGroup.Parts;
@@ -2011,7 +2668,16 @@ namespace OpenSim.Region.Framework.Scenes
2011 { 2668 {
2012 SceneObjectPart part = ogParts[i]; 2669 SceneObjectPart part = ogParts[i];
2013 if (part.UUID != objectGroup.m_rootPart.UUID) 2670 if (part.UUID != objectGroup.m_rootPart.UUID)
2671 {
2014 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2672 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2673 // let physics know
2674 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2675 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2676 {
2677 part.PhysActor.link(m_rootPart.PhysActor);
2678 this.Scene.PhysicsScene.AddPhysicsActorTaint(part.PhysActor);
2679 }
2680 }
2015 part.ClearUndoState(); 2681 part.ClearUndoState();
2016 } 2682 }
2017 } 2683 }
@@ -2020,7 +2686,7 @@ namespace OpenSim.Region.Framework.Scenes
2020 objectGroup.IsDeleted = true; 2686 objectGroup.IsDeleted = true;
2021 2687
2022 objectGroup.m_parts.Clear(); 2688 objectGroup.m_parts.Clear();
2023 2689
2024 // Can't do this yet since backup still makes use of the root part without any synchronization 2690 // Can't do this yet since backup still makes use of the root part without any synchronization
2025// objectGroup.m_rootPart = null; 2691// objectGroup.m_rootPart = null;
2026 2692
@@ -2031,6 +2697,9 @@ namespace OpenSim.Region.Framework.Scenes
2031 // unmoved prims! 2697 // unmoved prims!
2032 ResetChildPrimPhysicsPositions(); 2698 ResetChildPrimPhysicsPositions();
2033 2699
2700 if (m_rootPart.PhysActor != null)
2701 m_rootPart.PhysActor.Building = false;
2702
2034 //HasGroupChanged = true; 2703 //HasGroupChanged = true;
2035 //ScheduleGroupForFullUpdate(); 2704 //ScheduleGroupForFullUpdate();
2036 } 2705 }
@@ -2083,7 +2752,10 @@ namespace OpenSim.Region.Framework.Scenes
2083// m_log.DebugFormat( 2752// m_log.DebugFormat(
2084// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 2753// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2085// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 2754// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2086 2755
2756 if (m_rootPart.PhysActor != null)
2757 m_rootPart.PhysActor.Building = true;
2758
2087 linkPart.ClearUndoState(); 2759 linkPart.ClearUndoState();
2088 2760
2089 Quaternion worldRot = linkPart.GetWorldRotation(); 2761 Quaternion worldRot = linkPart.GetWorldRotation();
@@ -2143,6 +2815,14 @@ namespace OpenSim.Region.Framework.Scenes
2143 2815
2144 // When we delete a group, we currently have to force persist to the database if the object id has changed 2816 // When we delete a group, we currently have to force persist to the database if the object id has changed
2145 // (since delete works by deleting all rows which have a given object id) 2817 // (since delete works by deleting all rows which have a given object id)
2818
2819 // this is as it seems to be in sl now
2820 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2821 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2822
2823 if (m_rootPart.PhysActor != null)
2824 m_rootPart.PhysActor.Building = false;
2825
2146 objectGroup.HasGroupChangedDueToDelink = true; 2826 objectGroup.HasGroupChangedDueToDelink = true;
2147 2827
2148 return objectGroup; 2828 return objectGroup;
@@ -2154,6 +2834,7 @@ namespace OpenSim.Region.Framework.Scenes
2154 /// <param name="objectGroup"></param> 2834 /// <param name="objectGroup"></param>
2155 public virtual void DetachFromBackup() 2835 public virtual void DetachFromBackup()
2156 { 2836 {
2837 m_scene.SceneGraph.FireDetachFromBackup(this);
2157 if (m_isBackedUp && Scene != null) 2838 if (m_isBackedUp && Scene != null)
2158 m_scene.EventManager.OnBackup -= ProcessBackup; 2839 m_scene.EventManager.OnBackup -= ProcessBackup;
2159 2840
@@ -2172,7 +2853,8 @@ namespace OpenSim.Region.Framework.Scenes
2172 2853
2173 axPos *= parentRot; 2854 axPos *= parentRot;
2174 part.OffsetPosition = axPos; 2855 part.OffsetPosition = axPos;
2175 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2856 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2857 part.GroupPosition = newPos;
2176 part.OffsetPosition = Vector3.Zero; 2858 part.OffsetPosition = Vector3.Zero;
2177 part.RotationOffset = worldRot; 2859 part.RotationOffset = worldRot;
2178 2860
@@ -2183,7 +2865,7 @@ namespace OpenSim.Region.Framework.Scenes
2183 2865
2184 part.LinkNum = linkNum; 2866 part.LinkNum = linkNum;
2185 2867
2186 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2868 part.OffsetPosition = newPos - AbsolutePosition;
2187 2869
2188 Quaternion rootRotation = m_rootPart.RotationOffset; 2870 Quaternion rootRotation = m_rootPart.RotationOffset;
2189 2871
@@ -2193,7 +2875,7 @@ namespace OpenSim.Region.Framework.Scenes
2193 2875
2194 parentRot = m_rootPart.RotationOffset; 2876 parentRot = m_rootPart.RotationOffset;
2195 oldRot = part.RotationOffset; 2877 oldRot = part.RotationOffset;
2196 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2878 Quaternion newRot = Quaternion.Inverse(parentRot) * worldRot;
2197 part.RotationOffset = newRot; 2879 part.RotationOffset = newRot;
2198 } 2880 }
2199 2881
@@ -2445,8 +3127,31 @@ namespace OpenSim.Region.Framework.Scenes
2445 } 3127 }
2446 } 3128 }
2447 3129
3130/*
3131 RootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
2448 for (int i = 0; i < parts.Length; i++) 3132 for (int i = 0; i < parts.Length; i++)
2449 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3133 {
3134 if (parts[i] != RootPart)
3135 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect);
3136 }
3137*/
3138 if (parts.Length > 1)
3139 {
3140 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3141
3142 for (int i = 0; i < parts.Length; i++)
3143 {
3144
3145 if (parts[i].UUID != m_rootPart.UUID)
3146 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3147 }
3148
3149 if (m_rootPart.PhysActor != null)
3150 m_rootPart.PhysActor.Building = false;
3151 }
3152 else
3153 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
3154
2450 } 3155 }
2451 } 3156 }
2452 3157
@@ -2459,6 +3164,17 @@ namespace OpenSim.Region.Framework.Scenes
2459 } 3164 }
2460 } 3165 }
2461 3166
3167
3168
3169 /// <summary>
3170 /// Gets the number of parts
3171 /// </summary>
3172 /// <returns></returns>
3173 public int GetPartCount()
3174 {
3175 return Parts.Count();
3176 }
3177
2462 /// <summary> 3178 /// <summary>
2463 /// Update the texture entry for this part 3179 /// Update the texture entry for this part
2464 /// </summary> 3180 /// </summary>
@@ -2520,11 +3236,6 @@ namespace OpenSim.Region.Framework.Scenes
2520 /// <param name="scale"></param> 3236 /// <param name="scale"></param>
2521 public void GroupResize(Vector3 scale) 3237 public void GroupResize(Vector3 scale)
2522 { 3238 {
2523// m_log.DebugFormat(
2524// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2525
2526 RootPart.StoreUndoState(true);
2527
2528 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3239 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2529 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3240 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
2530 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); 3241 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
@@ -2551,7 +3262,6 @@ namespace OpenSim.Region.Framework.Scenes
2551 SceneObjectPart obPart = parts[i]; 3262 SceneObjectPart obPart = parts[i];
2552 if (obPart.UUID != m_rootPart.UUID) 3263 if (obPart.UUID != m_rootPart.UUID)
2553 { 3264 {
2554// obPart.IgnoreUndoUpdate = true;
2555 Vector3 oldSize = new Vector3(obPart.Scale); 3265 Vector3 oldSize = new Vector3(obPart.Scale);
2556 3266
2557 float f = 1.0f; 3267 float f = 1.0f;
@@ -2615,8 +3325,6 @@ namespace OpenSim.Region.Framework.Scenes
2615 z *= a; 3325 z *= a;
2616 } 3326 }
2617 } 3327 }
2618
2619// obPart.IgnoreUndoUpdate = false;
2620 } 3328 }
2621 } 3329 }
2622 } 3330 }
@@ -2626,9 +3334,7 @@ namespace OpenSim.Region.Framework.Scenes
2626 prevScale.Y *= y; 3334 prevScale.Y *= y;
2627 prevScale.Z *= z; 3335 prevScale.Z *= z;
2628 3336
2629// RootPart.IgnoreUndoUpdate = true;
2630 RootPart.Resize(prevScale); 3337 RootPart.Resize(prevScale);
2631// RootPart.IgnoreUndoUpdate = false;
2632 3338
2633 parts = m_parts.GetArray(); 3339 parts = m_parts.GetArray();
2634 for (int i = 0; i < parts.Length; i++) 3340 for (int i = 0; i < parts.Length; i++)
@@ -2637,8 +3343,6 @@ namespace OpenSim.Region.Framework.Scenes
2637 3343
2638 if (obPart.UUID != m_rootPart.UUID) 3344 if (obPart.UUID != m_rootPart.UUID)
2639 { 3345 {
2640 obPart.IgnoreUndoUpdate = true;
2641
2642 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3346 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2643 currentpos.X *= x; 3347 currentpos.X *= x;
2644 currentpos.Y *= y; 3348 currentpos.Y *= y;
@@ -2651,16 +3355,12 @@ namespace OpenSim.Region.Framework.Scenes
2651 3355
2652 obPart.Resize(newSize); 3356 obPart.Resize(newSize);
2653 obPart.UpdateOffSet(currentpos); 3357 obPart.UpdateOffSet(currentpos);
2654
2655 obPart.IgnoreUndoUpdate = false;
2656 } 3358 }
2657 3359
2658// obPart.IgnoreUndoUpdate = false; 3360 HasGroupChanged = true;
2659// obPart.StoreUndoState(); 3361 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3362 ScheduleGroupForTerseUpdate();
2660 } 3363 }
2661
2662// m_log.DebugFormat(
2663// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
2664 } 3364 }
2665 3365
2666 #endregion 3366 #endregion
@@ -2673,14 +3373,6 @@ namespace OpenSim.Region.Framework.Scenes
2673 /// <param name="pos"></param> 3373 /// <param name="pos"></param>
2674 public void UpdateGroupPosition(Vector3 pos) 3374 public void UpdateGroupPosition(Vector3 pos)
2675 { 3375 {
2676// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2677
2678 RootPart.StoreUndoState(true);
2679
2680// SceneObjectPart[] parts = m_parts.GetArray();
2681// for (int i = 0; i < parts.Length; i++)
2682// parts[i].StoreUndoState();
2683
2684 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3376 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2685 { 3377 {
2686 if (IsAttachment) 3378 if (IsAttachment)
@@ -2712,21 +3404,17 @@ namespace OpenSim.Region.Framework.Scenes
2712 /// </summary> 3404 /// </summary>
2713 /// <param name="pos"></param> 3405 /// <param name="pos"></param>
2714 /// <param name="localID"></param> 3406 /// <param name="localID"></param>
3407 ///
3408
2715 public void UpdateSinglePosition(Vector3 pos, uint localID) 3409 public void UpdateSinglePosition(Vector3 pos, uint localID)
2716 { 3410 {
2717 SceneObjectPart part = GetPart(localID); 3411 SceneObjectPart part = GetPart(localID);
2718 3412
2719// SceneObjectPart[] parts = m_parts.GetArray();
2720// for (int i = 0; i < parts.Length; i++)
2721// parts[i].StoreUndoState();
2722
2723 if (part != null) 3413 if (part != null)
2724 { 3414 {
2725// m_log.DebugFormat( 3415// unlock parts position change
2726// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3416 if (m_rootPart.PhysActor != null)
2727 3417 m_rootPart.PhysActor.Building = true;
2728 part.StoreUndoState(false);
2729 part.IgnoreUndoUpdate = true;
2730 3418
2731 if (part.UUID == m_rootPart.UUID) 3419 if (part.UUID == m_rootPart.UUID)
2732 { 3420 {
@@ -2737,8 +3425,10 @@ namespace OpenSim.Region.Framework.Scenes
2737 part.UpdateOffSet(pos); 3425 part.UpdateOffSet(pos);
2738 } 3426 }
2739 3427
3428 if (m_rootPart.PhysActor != null)
3429 m_rootPart.PhysActor.Building = false;
3430
2740 HasGroupChanged = true; 3431 HasGroupChanged = true;
2741 part.IgnoreUndoUpdate = false;
2742 } 3432 }
2743 } 3433 }
2744 3434
@@ -2748,13 +3438,7 @@ namespace OpenSim.Region.Framework.Scenes
2748 /// <param name="pos"></param> 3438 /// <param name="pos"></param>
2749 public void UpdateRootPosition(Vector3 pos) 3439 public void UpdateRootPosition(Vector3 pos)
2750 { 3440 {
2751// m_log.DebugFormat( 3441 // needs to be called with phys building true
2752// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
2753
2754// SceneObjectPart[] parts = m_parts.GetArray();
2755// for (int i = 0; i < parts.Length; i++)
2756// parts[i].StoreUndoState();
2757
2758 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3442 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2759 Vector3 oldPos = 3443 Vector3 oldPos =
2760 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3444 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
@@ -2777,7 +3461,14 @@ namespace OpenSim.Region.Framework.Scenes
2777 AbsolutePosition = newPos; 3461 AbsolutePosition = newPos;
2778 3462
2779 HasGroupChanged = true; 3463 HasGroupChanged = true;
2780 ScheduleGroupForTerseUpdate(); 3464 if (m_rootPart.Undoing)
3465 {
3466 ScheduleGroupForFullUpdate();
3467 }
3468 else
3469 {
3470 ScheduleGroupForTerseUpdate();
3471 }
2781 } 3472 }
2782 3473
2783 #endregion 3474 #endregion
@@ -2790,17 +3481,6 @@ namespace OpenSim.Region.Framework.Scenes
2790 /// <param name="rot"></param> 3481 /// <param name="rot"></param>
2791 public void UpdateGroupRotationR(Quaternion rot) 3482 public void UpdateGroupRotationR(Quaternion rot)
2792 { 3483 {
2793// m_log.DebugFormat(
2794// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
2795
2796// SceneObjectPart[] parts = m_parts.GetArray();
2797// for (int i = 0; i < parts.Length; i++)
2798// parts[i].StoreUndoState();
2799
2800 m_rootPart.StoreUndoState(true);
2801
2802 m_rootPart.UpdateRotation(rot);
2803
2804 PhysicsActor actor = m_rootPart.PhysActor; 3484 PhysicsActor actor = m_rootPart.PhysActor;
2805 if (actor != null) 3485 if (actor != null)
2806 { 3486 {
@@ -2819,16 +3499,6 @@ namespace OpenSim.Region.Framework.Scenes
2819 /// <param name="rot"></param> 3499 /// <param name="rot"></param>
2820 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3500 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
2821 { 3501 {
2822// m_log.DebugFormat(
2823// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
2824
2825// SceneObjectPart[] parts = m_parts.GetArray();
2826// for (int i = 0; i < parts.Length; i++)
2827// parts[i].StoreUndoState();
2828
2829 RootPart.StoreUndoState(true);
2830 RootPart.IgnoreUndoUpdate = true;
2831
2832 m_rootPart.UpdateRotation(rot); 3502 m_rootPart.UpdateRotation(rot);
2833 3503
2834 PhysicsActor actor = m_rootPart.PhysActor; 3504 PhysicsActor actor = m_rootPart.PhysActor;
@@ -2842,8 +3512,6 @@ namespace OpenSim.Region.Framework.Scenes
2842 3512
2843 HasGroupChanged = true; 3513 HasGroupChanged = true;
2844 ScheduleGroupForTerseUpdate(); 3514 ScheduleGroupForTerseUpdate();
2845
2846 RootPart.IgnoreUndoUpdate = false;
2847 } 3515 }
2848 3516
2849 /// <summary> 3517 /// <summary>
@@ -2856,13 +3524,11 @@ namespace OpenSim.Region.Framework.Scenes
2856 SceneObjectPart part = GetPart(localID); 3524 SceneObjectPart part = GetPart(localID);
2857 3525
2858 SceneObjectPart[] parts = m_parts.GetArray(); 3526 SceneObjectPart[] parts = m_parts.GetArray();
2859 for (int i = 0; i < parts.Length; i++)
2860 parts[i].StoreUndoState();
2861 3527
2862 if (part != null) 3528 if (part != null)
2863 { 3529 {
2864// m_log.DebugFormat( 3530 if (m_rootPart.PhysActor != null)
2865// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 3531 m_rootPart.PhysActor.Building = true;
2866 3532
2867 if (part.UUID == m_rootPart.UUID) 3533 if (part.UUID == m_rootPart.UUID)
2868 { 3534 {
@@ -2872,6 +3538,9 @@ namespace OpenSim.Region.Framework.Scenes
2872 { 3538 {
2873 part.UpdateRotation(rot); 3539 part.UpdateRotation(rot);
2874 } 3540 }
3541
3542 if (m_rootPart.PhysActor != null)
3543 m_rootPart.PhysActor.Building = false;
2875 } 3544 }
2876 } 3545 }
2877 3546
@@ -2885,12 +3554,8 @@ namespace OpenSim.Region.Framework.Scenes
2885 SceneObjectPart part = GetPart(localID); 3554 SceneObjectPart part = GetPart(localID);
2886 if (part != null) 3555 if (part != null)
2887 { 3556 {
2888// m_log.DebugFormat( 3557 if (m_rootPart.PhysActor != null)
2889// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 3558 m_rootPart.PhysActor.Building = true;
2890// part.Name, part.LocalId, rot);
2891
2892 part.StoreUndoState();
2893 part.IgnoreUndoUpdate = true;
2894 3559
2895 if (part.UUID == m_rootPart.UUID) 3560 if (part.UUID == m_rootPart.UUID)
2896 { 3561 {
@@ -2903,7 +3568,8 @@ namespace OpenSim.Region.Framework.Scenes
2903 part.OffsetPosition = pos; 3568 part.OffsetPosition = pos;
2904 } 3569 }
2905 3570
2906 part.IgnoreUndoUpdate = false; 3571 if (m_rootPart.PhysActor != null)
3572 m_rootPart.PhysActor.Building = false;
2907 } 3573 }
2908 } 3574 }
2909 3575
@@ -2913,15 +3579,12 @@ namespace OpenSim.Region.Framework.Scenes
2913 /// <param name="rot"></param> 3579 /// <param name="rot"></param>
2914 public void UpdateRootRotation(Quaternion rot) 3580 public void UpdateRootRotation(Quaternion rot)
2915 { 3581 {
2916// m_log.DebugFormat( 3582 // needs to be called with phys building true
2917// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
2918// Name, LocalId, rot);
2919
2920 Quaternion axRot = rot; 3583 Quaternion axRot = rot;
2921 Quaternion oldParentRot = m_rootPart.RotationOffset; 3584 Quaternion oldParentRot = m_rootPart.RotationOffset;
2922 3585
2923 m_rootPart.StoreUndoState(); 3586 //Don't use UpdateRotation because it schedules an update prematurely
2924 m_rootPart.UpdateRotation(rot); 3587 m_rootPart.RotationOffset = rot;
2925 3588
2926 PhysicsActor pa = m_rootPart.PhysActor; 3589 PhysicsActor pa = m_rootPart.PhysActor;
2927 3590
@@ -2937,35 +3600,135 @@ namespace OpenSim.Region.Framework.Scenes
2937 SceneObjectPart prim = parts[i]; 3600 SceneObjectPart prim = parts[i];
2938 if (prim.UUID != m_rootPart.UUID) 3601 if (prim.UUID != m_rootPart.UUID)
2939 { 3602 {
2940 prim.IgnoreUndoUpdate = true; 3603 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3604 NewRot = Quaternion.Inverse(axRot) * NewRot;
3605 prim.RotationOffset = NewRot;
3606
2941 Vector3 axPos = prim.OffsetPosition; 3607 Vector3 axPos = prim.OffsetPosition;
3608
2942 axPos *= oldParentRot; 3609 axPos *= oldParentRot;
2943 axPos *= Quaternion.Inverse(axRot); 3610 axPos *= Quaternion.Inverse(axRot);
2944 prim.OffsetPosition = axPos; 3611 prim.OffsetPosition = axPos;
2945 Quaternion primsRot = prim.RotationOffset; 3612 }
2946 Quaternion newRot = oldParentRot * primsRot; 3613 }
2947 newRot = Quaternion.Inverse(axRot) * newRot;
2948 prim.RotationOffset = newRot;
2949 prim.ScheduleTerseUpdate();
2950 prim.IgnoreUndoUpdate = false;
2951 }
2952 }
2953
2954// for (int i = 0; i < parts.Length; i++)
2955// {
2956// SceneObjectPart childpart = parts[i];
2957// if (childpart != m_rootPart)
2958// {
2959//// childpart.IgnoreUndoUpdate = false;
2960//// childpart.StoreUndoState();
2961// }
2962// }
2963 3614
2964 m_rootPart.ScheduleTerseUpdate(); 3615 HasGroupChanged = true;
3616 ScheduleGroupForFullUpdate();
3617 }
2965 3618
2966// m_log.DebugFormat( 3619 private enum updatetype :int
2967// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3620 {
2968// Name, LocalId, rot); 3621 none = 0,
3622 partterse = 1,
3623 partfull = 2,
3624 groupterse = 3,
3625 groupfull = 4
3626 }
3627
3628 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3629 {
3630 // TODO this still as excessive *.Schedule*Update()s
3631
3632 if (part != null && part.ParentGroup != null)
3633 {
3634 ObjectChangeType change = data.change;
3635 bool togroup = ((change & ObjectChangeType.Group) != 0);
3636 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
3637
3638 SceneObjectGroup group = part.ParentGroup;
3639 PhysicsActor pha = group.RootPart.PhysActor;
3640
3641 updatetype updateType = updatetype.none;
3642
3643 if (togroup)
3644 {
3645 // related to group
3646 if ((change & ObjectChangeType.Position) != 0)
3647 {
3648 group.AbsolutePosition = data.position;
3649 updateType = updatetype.groupterse;
3650 }
3651 if ((change & ObjectChangeType.Rotation) != 0)
3652 {
3653 group.RootPart.UpdateRotation(data.rotation);
3654 updateType = updatetype.none;
3655 }
3656 if ((change & ObjectChangeType.Scale) != 0)
3657 {
3658 if (pha != null)
3659 pha.Building = true;
3660
3661 group.GroupResize(data.scale);
3662 updateType = updatetype.none;
3663
3664 if (pha != null)
3665 pha.Building = false;
3666 }
3667 }
3668 else
3669 {
3670 // related to single prim in a link-set ( ie group)
3671 if (pha != null)
3672 pha.Building = true;
3673
3674 // root part is special
3675 // parts offset positions or rotations need to change also
3676
3677 if (part == group.RootPart)
3678 {
3679 if ((change & ObjectChangeType.Position) != 0)
3680 group.UpdateRootPosition(data.position);
3681 if ((change & ObjectChangeType.Rotation) != 0)
3682 group.UpdateRootRotation(data.rotation);
3683 if ((change & ObjectChangeType.Scale) != 0)
3684 part.Resize(data.scale);
3685 }
3686 else
3687 {
3688 if ((change & ObjectChangeType.Position) != 0)
3689 {
3690 part.OffsetPosition = data.position;
3691 updateType = updatetype.partterse;
3692 }
3693 if ((change & ObjectChangeType.Rotation) != 0)
3694 {
3695 part.UpdateRotation(data.rotation);
3696 updateType = updatetype.none;
3697 }
3698 if ((change & ObjectChangeType.Scale) != 0)
3699 {
3700 part.Resize(data.scale);
3701 updateType = updatetype.none;
3702 }
3703 }
3704
3705 if (pha != null)
3706 pha.Building = false;
3707 }
3708
3709 if (updateType != updatetype.none)
3710 {
3711 group.HasGroupChanged = true;
3712
3713 switch (updateType)
3714 {
3715 case updatetype.partterse:
3716 part.ScheduleTerseUpdate();
3717 break;
3718 case updatetype.partfull:
3719 part.ScheduleFullUpdate();
3720 break;
3721 case updatetype.groupterse:
3722 group.ScheduleGroupForTerseUpdate();
3723 break;
3724 case updatetype.groupfull:
3725 group.ScheduleGroupForFullUpdate();
3726 break;
3727 default:
3728 break;
3729 }
3730 }
3731 }
2969 } 3732 }
2970 3733
2971 #endregion 3734 #endregion
@@ -3189,7 +3952,6 @@ namespace OpenSim.Region.Framework.Scenes
3189 public float GetMass() 3952 public float GetMass()
3190 { 3953 {
3191 float retmass = 0f; 3954 float retmass = 0f;
3192
3193 SceneObjectPart[] parts = m_parts.GetArray(); 3955 SceneObjectPart[] parts = m_parts.GetArray();
3194 for (int i = 0; i < parts.Length; i++) 3956 for (int i = 0; i < parts.Length; i++)
3195 retmass += parts[i].GetMass(); 3957 retmass += parts[i].GetMass();
@@ -3285,6 +4047,14 @@ namespace OpenSim.Region.Framework.Scenes
3285 SetFromItemID(uuid); 4047 SetFromItemID(uuid);
3286 } 4048 }
3287 4049
4050 public void ResetOwnerChangeFlag()
4051 {
4052 ForEachPart(delegate(SceneObjectPart part)
4053 {
4054 part.ResetOwnerChangeFlag();
4055 });
4056 }
4057
3288 #endregion 4058 #endregion
3289 } 4059 }
3290} 4060}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 2b1fba0..aed25a7 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.
@@ -192,6 +193,15 @@ namespace OpenSim.Region.Framework.Scenes
192 193
193 public UUID FromFolderID; 194 public UUID FromFolderID;
194 195
196 // The following two are to hold the attachment data
197 // while an object is inworld
198 [XmlIgnore]
199 public byte AttachPoint = 0;
200
201 [XmlIgnore]
202 public Vector3 AttachOffset = Vector3.Zero;
203
204 [XmlIgnore]
195 public int STATUS_ROTATE_X; 205 public int STATUS_ROTATE_X;
196 206
197 public int STATUS_ROTATE_Y; 207 public int STATUS_ROTATE_Y;
@@ -218,8 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
218 228
219 public Vector3 RotationAxis = Vector3.One; 229 public Vector3 RotationAxis = Vector3.One;
220 230
221 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 231 public bool VolumeDetectActive;
222 // Certainly this must be a persistant setting finally
223 232
224 public bool IsWaitingForFirstSpinUpdatePacket; 233 public bool IsWaitingForFirstSpinUpdatePacket;
225 234
@@ -259,10 +268,10 @@ namespace OpenSim.Region.Framework.Scenes
259 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 268 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
260 private Vector3 m_sitTargetPosition; 269 private Vector3 m_sitTargetPosition;
261 private string m_sitAnimation = "SIT"; 270 private string m_sitAnimation = "SIT";
271 private bool m_occupied; // KF if any av is sitting on this prim
262 private string m_text = String.Empty; 272 private string m_text = String.Empty;
263 private string m_touchName = String.Empty; 273 private string m_touchName = String.Empty;
264 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 274 private UndoRedoState m_UndoRedo = null;
265 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5);
266 275
267 private bool m_passTouches; 276 private bool m_passTouches;
268 277
@@ -291,7 +300,16 @@ namespace OpenSim.Region.Framework.Scenes
291 protected Vector3 m_lastAcceleration; 300 protected Vector3 m_lastAcceleration;
292 protected Vector3 m_lastAngularVelocity; 301 protected Vector3 m_lastAngularVelocity;
293 protected int m_lastTerseSent; 302 protected int m_lastTerseSent;
294 303 protected float m_buoyancy = 0.0f;
304 protected Vector3 m_force;
305 protected Vector3 m_torque;
306
307 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
308 protected float m_density = 1000.0f; // in kg/m^3
309 protected float m_gravitymod = 1.0f;
310 protected float m_friction = 0.6f; // wood
311 protected float m_bounce = 0.5f; // wood
312
295 /// <summary> 313 /// <summary>
296 /// Stores media texture data 314 /// Stores media texture data
297 /// </summary> 315 /// </summary>
@@ -307,6 +325,17 @@ namespace OpenSim.Region.Framework.Scenes
307 private UUID m_collisionSound; 325 private UUID m_collisionSound;
308 private float m_collisionSoundVolume; 326 private float m_collisionSoundVolume;
309 327
328
329 private SOPVehicle m_vehicle = null;
330
331 private KeyframeMotion m_keyframeMotion = null;
332
333 public KeyframeMotion KeyframeMotion
334 {
335 get; set;
336 }
337
338
310 #endregion Fields 339 #endregion Fields
311 340
312// ~SceneObjectPart() 341// ~SceneObjectPart()
@@ -349,7 +378,7 @@ namespace OpenSim.Region.Framework.Scenes
349 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 378 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
350 Quaternion rotationOffset, Vector3 offsetPosition) : this() 379 Quaternion rotationOffset, Vector3 offsetPosition) : this()
351 { 380 {
352 m_name = "Primitive"; 381 m_name = "Object";
353 382
354 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 383 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
355 LastOwnerID = CreatorID = OwnerID = ownerID; 384 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -389,7 +418,7 @@ namespace OpenSim.Region.Framework.Scenes
389 private uint _ownerMask = (uint)PermissionMask.All; 418 private uint _ownerMask = (uint)PermissionMask.All;
390 private uint _groupMask = (uint)PermissionMask.None; 419 private uint _groupMask = (uint)PermissionMask.None;
391 private uint _everyoneMask = (uint)PermissionMask.None; 420 private uint _everyoneMask = (uint)PermissionMask.None;
392 private uint _nextOwnerMask = (uint)PermissionMask.All; 421 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
393 private PrimFlags _flags = PrimFlags.None; 422 private PrimFlags _flags = PrimFlags.None;
394 private DateTime m_expires; 423 private DateTime m_expires;
395 private DateTime m_rezzed; 424 private DateTime m_rezzed;
@@ -483,12 +512,16 @@ namespace OpenSim.Region.Framework.Scenes
483 } 512 }
484 513
485 /// <value> 514 /// <value>
486 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 515 /// Get the inventory list
487 /// </value> 516 /// </value>
488 public TaskInventoryDictionary TaskInventory 517 public TaskInventoryDictionary TaskInventory
489 { 518 {
490 get { return m_inventory.Items; } 519 get {
491 set { m_inventory.Items = value; } 520 return m_inventory.Items;
521 }
522 set {
523 m_inventory.Items = value;
524 }
492 } 525 }
493 526
494 /// <summary> 527 /// <summary>
@@ -538,20 +571,6 @@ namespace OpenSim.Region.Framework.Scenes
538 } 571 }
539 } 572 }
540 573
541 public byte Material
542 {
543 get { return (byte) m_material; }
544 set
545 {
546 m_material = (Material)value;
547
548 PhysicsActor pa = PhysActor;
549
550 if (pa != null)
551 pa.SetMaterial((int)value);
552 }
553 }
554
555 public bool PassTouches 574 public bool PassTouches
556 { 575 {
557 get { return m_passTouches; } 576 get { return m_passTouches; }
@@ -634,14 +653,12 @@ namespace OpenSim.Region.Framework.Scenes
634 set { m_LoopSoundSlavePrims = value; } 653 set { m_LoopSoundSlavePrims = value; }
635 } 654 }
636 655
637
638 public Byte[] TextureAnimation 656 public Byte[] TextureAnimation
639 { 657 {
640 get { return m_TextureAnimation; } 658 get { return m_TextureAnimation; }
641 set { m_TextureAnimation = value; } 659 set { m_TextureAnimation = value; }
642 } 660 }
643 661
644
645 public Byte[] ParticleSystem 662 public Byte[] ParticleSystem
646 { 663 {
647 get { return m_particleSystem; } 664 get { return m_particleSystem; }
@@ -678,8 +695,12 @@ namespace OpenSim.Region.Framework.Scenes
678 { 695 {
679 // If this is a linkset, we don't want the physics engine mucking up our group position here. 696 // If this is a linkset, we don't want the physics engine mucking up our group position here.
680 PhysicsActor actor = PhysActor; 697 PhysicsActor actor = PhysActor;
681 if (actor != null && ParentID == 0) 698 if (ParentID == 0)
682 m_groupPosition = actor.Position; 699 {
700 if (actor != null)
701 m_groupPosition = actor.Position;
702 return m_groupPosition;
703 }
683 704
684 if (ParentGroup.IsAttachment) 705 if (ParentGroup.IsAttachment)
685 { 706 {
@@ -688,12 +709,14 @@ namespace OpenSim.Region.Framework.Scenes
688 return sp.AbsolutePosition; 709 return sp.AbsolutePosition;
689 } 710 }
690 711
712 // use root prim's group position. Physics may have updated it
713 if (ParentGroup.RootPart != this)
714 m_groupPosition = ParentGroup.RootPart.GroupPosition;
691 return m_groupPosition; 715 return m_groupPosition;
692 } 716 }
693 set 717 set
694 { 718 {
695 m_groupPosition = value; 719 m_groupPosition = value;
696
697 PhysicsActor actor = PhysActor; 720 PhysicsActor actor = PhysActor;
698 if (actor != null) 721 if (actor != null)
699 { 722 {
@@ -719,16 +742,6 @@ namespace OpenSim.Region.Framework.Scenes
719 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 742 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
720 } 743 }
721 } 744 }
722
723 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
724 if (SitTargetAvatar != UUID.Zero)
725 {
726 ScenePresence avatar;
727 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
728 {
729 avatar.ParentPosition = GetWorldPosition();
730 }
731 }
732 } 745 }
733 } 746 }
734 747
@@ -737,7 +750,7 @@ namespace OpenSim.Region.Framework.Scenes
737 get { return m_offsetPosition; } 750 get { return m_offsetPosition; }
738 set 751 set
739 { 752 {
740// StoreUndoState(); 753 Vector3 oldpos = m_offsetPosition;
741 m_offsetPosition = value; 754 m_offsetPosition = value;
742 755
743 if (ParentGroup != null && !ParentGroup.IsDeleted) 756 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -752,7 +765,22 @@ namespace OpenSim.Region.Framework.Scenes
752 if (ParentGroup.Scene != null) 765 if (ParentGroup.Scene != null)
753 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 766 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
754 } 767 }
768
769 if (!m_parentGroup.m_dupeInProgress)
770 {
771 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
772 foreach (ScenePresence av in avs)
773 {
774 if (av.ParentID == m_localId)
775 {
776 Vector3 offset = (m_offsetPosition - oldpos);
777 av.AbsolutePosition += offset;
778 av.SendAvatarDataToAllAgents();
779 }
780 }
781 }
755 } 782 }
783 TriggerScriptChangedEvent(Changed.POSITION);
756 } 784 }
757 } 785 }
758 786
@@ -801,7 +829,7 @@ namespace OpenSim.Region.Framework.Scenes
801 829
802 set 830 set
803 { 831 {
804 StoreUndoState(); 832// StoreUndoState();
805 m_rotationOffset = value; 833 m_rotationOffset = value;
806 834
807 PhysicsActor actor = PhysActor; 835 PhysicsActor actor = PhysActor;
@@ -889,7 +917,7 @@ namespace OpenSim.Region.Framework.Scenes
889 get 917 get
890 { 918 {
891 PhysicsActor actor = PhysActor; 919 PhysicsActor actor = PhysActor;
892 if ((actor != null) && actor.IsPhysical) 920 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
893 { 921 {
894 m_angularVelocity = actor.RotationalVelocity; 922 m_angularVelocity = actor.RotationalVelocity;
895 } 923 }
@@ -901,7 +929,16 @@ namespace OpenSim.Region.Framework.Scenes
901 /// <summary></summary> 929 /// <summary></summary>
902 public Vector3 Acceleration 930 public Vector3 Acceleration
903 { 931 {
904 get { return m_acceleration; } 932 get
933 {
934 PhysicsActor actor = PhysActor;
935 if (actor != null)
936 {
937 m_acceleration = actor.Acceleration;
938 }
939 return m_acceleration;
940 }
941
905 set { m_acceleration = value; } 942 set { m_acceleration = value; }
906 } 943 }
907 944
@@ -958,7 +995,10 @@ namespace OpenSim.Region.Framework.Scenes
958 public PrimitiveBaseShape Shape 995 public PrimitiveBaseShape Shape
959 { 996 {
960 get { return m_shape; } 997 get { return m_shape; }
961 set { m_shape = value;} 998 set
999 {
1000 m_shape = value;
1001 }
962 } 1002 }
963 1003
964 /// <summary> 1004 /// <summary>
@@ -971,7 +1011,6 @@ namespace OpenSim.Region.Framework.Scenes
971 { 1011 {
972 if (m_shape != null) 1012 if (m_shape != null)
973 { 1013 {
974 StoreUndoState();
975 1014
976 m_shape.Scale = value; 1015 m_shape.Scale = value;
977 1016
@@ -998,6 +1037,7 @@ namespace OpenSim.Region.Framework.Scenes
998 } 1037 }
999 1038
1000 public UpdateRequired UpdateFlag { get; set; } 1039 public UpdateRequired UpdateFlag { get; set; }
1040 public bool UpdatePhysRequired { get; set; }
1001 1041
1002 /// <summary> 1042 /// <summary>
1003 /// Used for media on a prim. 1043 /// Used for media on a prim.
@@ -1038,10 +1078,7 @@ namespace OpenSim.Region.Framework.Scenes
1038 { 1078 {
1039 get 1079 get
1040 { 1080 {
1041 if (ParentGroup.IsAttachment) 1081 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1042 return GroupPosition;
1043
1044 return m_offsetPosition + m_groupPosition;
1045 } 1082 }
1046 } 1083 }
1047 1084
@@ -1211,6 +1248,13 @@ namespace OpenSim.Region.Framework.Scenes
1211 _flags = value; 1248 _flags = value;
1212 } 1249 }
1213 } 1250 }
1251
1252 [XmlIgnore]
1253 public bool IsOccupied // KF If an av is sittingon this prim
1254 {
1255 get { return m_occupied; }
1256 set { m_occupied = value; }
1257 }
1214 1258
1215 /// <summary> 1259 /// <summary>
1216 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1260 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1270,6 +1314,316 @@ namespace OpenSim.Region.Framework.Scenes
1270 set { m_collisionSoundVolume = value; } 1314 set { m_collisionSoundVolume = value; }
1271 } 1315 }
1272 1316
1317 public float Buoyancy
1318 {
1319 get
1320 {
1321 if (ParentGroup.RootPart == this)
1322 return m_buoyancy;
1323
1324 return ParentGroup.RootPart.Buoyancy;
1325 }
1326 set
1327 {
1328 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1329 {
1330 ParentGroup.RootPart.Buoyancy = value;
1331 return;
1332 }
1333 m_buoyancy = value;
1334 if (PhysActor != null)
1335 PhysActor.Buoyancy = value;
1336 }
1337 }
1338
1339 public Vector3 Force
1340 {
1341 get
1342 {
1343 if (ParentGroup.RootPart == this)
1344 return m_force;
1345
1346 return ParentGroup.RootPart.Force;
1347 }
1348
1349 set
1350 {
1351 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1352 {
1353 ParentGroup.RootPart.Force = value;
1354 return;
1355 }
1356 m_force = value;
1357 if (PhysActor != null)
1358 PhysActor.Force = value;
1359 }
1360 }
1361
1362 public Vector3 Torque
1363 {
1364 get
1365 {
1366 if (ParentGroup.RootPart == this)
1367 return m_torque;
1368
1369 return ParentGroup.RootPart.Torque;
1370 }
1371
1372 set
1373 {
1374 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1375 {
1376 ParentGroup.RootPart.Torque = value;
1377 return;
1378 }
1379 m_torque = value;
1380 if (PhysActor != null)
1381 PhysActor.Torque = value;
1382 }
1383 }
1384
1385 public byte Material
1386 {
1387 get { return (byte)m_material; }
1388 set
1389 {
1390 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1391 {
1392 bool update = false;
1393
1394 if (m_material != (Material)value)
1395 {
1396 update = true;
1397 m_material = (Material)value;
1398 }
1399
1400 if (m_friction != SOPMaterialData.friction(m_material))
1401 {
1402 update = true;
1403 m_friction = SOPMaterialData.friction(m_material);
1404 }
1405
1406 if (m_bounce != SOPMaterialData.bounce(m_material))
1407 {
1408 update = true;
1409 m_bounce = SOPMaterialData.bounce(m_material);
1410 }
1411
1412 if (update)
1413 {
1414 if (PhysActor != null)
1415 {
1416 PhysActor.SetMaterial((int)value);
1417 }
1418 if(ParentGroup != null)
1419 ParentGroup.HasGroupChanged = true;
1420 ScheduleFullUpdateIfNone();
1421 UpdatePhysRequired = true;
1422 }
1423 }
1424 }
1425 }
1426
1427 // not a propriety to move to methods place later
1428 private bool HasMesh()
1429 {
1430 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1431 return true;
1432 return false;
1433 }
1434
1435 // not a propriety to move to methods place later
1436 public byte DefaultPhysicsShapeType()
1437 {
1438 byte type;
1439
1440 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1441 type = (byte)PhysShapeType.convex;
1442 else
1443 type = (byte)PhysShapeType.prim;
1444
1445 return type;
1446 }
1447
1448 [XmlIgnore]
1449 public bool UsesComplexCost
1450 {
1451 get
1452 {
1453 byte pst = PhysicsShapeType;
1454 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1455 return true;
1456 return false;
1457 }
1458 }
1459
1460 [XmlIgnore]
1461 public float PhysicsCost
1462 {
1463 get
1464 {
1465 if(PhysicsShapeType == (byte)PhysShapeType.none)
1466 return 0;
1467
1468 float cost = 0.1f;
1469 if (PhysActor != null)
1470// cost += PhysActor.Cost;
1471
1472 if ((Flags & PrimFlags.Physics) != 0)
1473 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1474 return cost;
1475 }
1476 }
1477
1478 [XmlIgnore]
1479 public float StreamingCost
1480 {
1481 get
1482 {
1483
1484
1485 return 0.1f;
1486 }
1487 }
1488
1489 [XmlIgnore]
1490 public float SimulationCost
1491 {
1492 get
1493 {
1494 // ignoring scripts. Don't like considering them for this
1495 if((Flags & PrimFlags.Physics) != 0)
1496 return 1.0f;
1497
1498 return 0.5f;
1499 }
1500 }
1501
1502 public byte PhysicsShapeType
1503 {
1504 get { return m_physicsShapeType; }
1505 set
1506 {
1507 byte oldv = m_physicsShapeType;
1508
1509 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1510 {
1511 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1512 m_physicsShapeType = DefaultPhysicsShapeType();
1513 else
1514 m_physicsShapeType = value;
1515 }
1516 else
1517 m_physicsShapeType = DefaultPhysicsShapeType();
1518
1519 if (m_physicsShapeType != oldv && ParentGroup != null)
1520 {
1521 if (m_physicsShapeType == (byte)PhysShapeType.none)
1522 {
1523 if (PhysActor != null)
1524 {
1525 Velocity = new Vector3(0, 0, 0);
1526 Acceleration = new Vector3(0, 0, 0);
1527 if (ParentGroup.RootPart == this)
1528 AngularVelocity = new Vector3(0, 0, 0);
1529 ParentGroup.Scene.RemovePhysicalPrim(1);
1530 RemoveFromPhysics();
1531 }
1532 }
1533 else if (PhysActor == null)
1534 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1535 else
1536 {
1537 PhysActor.PhysicsShapeType = m_physicsShapeType;
1538 if (Shape.SculptEntry)
1539 CheckSculptAndLoad();
1540 }
1541
1542 if (ParentGroup != null)
1543 ParentGroup.HasGroupChanged = true;
1544 }
1545
1546 if (m_physicsShapeType != value)
1547 {
1548 UpdatePhysRequired = true;
1549 }
1550 }
1551 }
1552
1553 public float Density // in kg/m^3
1554 {
1555 get { return m_density; }
1556 set
1557 {
1558 if (value >=1 && value <= 22587.0)
1559 {
1560 m_density = value;
1561 UpdatePhysRequired = true;
1562 }
1563
1564 ScheduleFullUpdateIfNone();
1565
1566 if (ParentGroup != null)
1567 ParentGroup.HasGroupChanged = true;
1568 }
1569 }
1570
1571 public float GravityModifier
1572 {
1573 get { return m_gravitymod; }
1574 set
1575 {
1576 if( value >= -1 && value <=28.0f)
1577 {
1578 m_gravitymod = value;
1579 UpdatePhysRequired = true;
1580 }
1581
1582 ScheduleFullUpdateIfNone();
1583
1584 if (ParentGroup != null)
1585 ParentGroup.HasGroupChanged = true;
1586
1587 }
1588 }
1589
1590 public float Friction
1591 {
1592 get { return m_friction; }
1593 set
1594 {
1595 if (value >= 0 && value <= 255.0f)
1596 {
1597 m_friction = value;
1598 UpdatePhysRequired = true;
1599 }
1600
1601 ScheduleFullUpdateIfNone();
1602
1603 if (ParentGroup != null)
1604 ParentGroup.HasGroupChanged = true;
1605 }
1606 }
1607
1608 public float Bounciness
1609 {
1610 get { return m_bounce; }
1611 set
1612 {
1613 if (value >= 0 && value <= 1.0f)
1614 {
1615 m_bounce = value;
1616 UpdatePhysRequired = true;
1617 }
1618
1619 ScheduleFullUpdateIfNone();
1620
1621 if (ParentGroup != null)
1622 ParentGroup.HasGroupChanged = true;
1623 }
1624 }
1625
1626
1273 #endregion Public Properties with only Get 1627 #endregion Public Properties with only Get
1274 1628
1275 private uint ApplyMask(uint val, bool set, uint mask) 1629 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1435,7 +1789,7 @@ namespace OpenSim.Region.Framework.Scenes
1435 impulse = newimpulse; 1789 impulse = newimpulse;
1436 } 1790 }
1437 1791
1438 ParentGroup.applyAngularImpulse(impulse); 1792 ParentGroup.setAngularImpulse(impulse);
1439 } 1793 }
1440 1794
1441 /// <summary> 1795 /// <summary>
@@ -1445,20 +1799,24 @@ namespace OpenSim.Region.Framework.Scenes
1445 /// </summary> 1799 /// </summary>
1446 /// <param name="impulsei">Vector force</param> 1800 /// <param name="impulsei">Vector force</param>
1447 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1801 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1448 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1802
1803 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1804 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1449 { 1805 {
1450 Vector3 impulse = impulsei; 1806 Vector3 torque = torquei;
1451 1807
1452 if (localGlobalTF) 1808 if (localGlobalTF)
1453 { 1809 {
1810/*
1454 Quaternion grot = GetWorldRotation(); 1811 Quaternion grot = GetWorldRotation();
1455 Quaternion AXgrot = grot; 1812 Quaternion AXgrot = grot;
1456 Vector3 AXimpulsei = impulsei; 1813 Vector3 AXimpulsei = impulsei;
1457 Vector3 newimpulse = AXimpulsei * AXgrot; 1814 Vector3 newimpulse = AXimpulsei * AXgrot;
1458 impulse = newimpulse; 1815 */
1816 torque *= GetWorldRotation();
1459 } 1817 }
1460 1818
1461 ParentGroup.setAngularImpulse(impulse); 1819 Torque = torque;
1462 } 1820 }
1463 1821
1464 /// <summary> 1822 /// <summary>
@@ -1466,18 +1824,19 @@ namespace OpenSim.Region.Framework.Scenes
1466 /// </summary> 1824 /// </summary>
1467 /// <param name="rootObjectFlags"></param> 1825 /// <param name="rootObjectFlags"></param>
1468 /// <param name="VolumeDetectActive"></param> 1826 /// <param name="VolumeDetectActive"></param>
1469 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 1827
1828 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive, bool building)
1470 { 1829 {
1471 if (!ParentGroup.Scene.CollidablePrims) 1830 if (!ParentGroup.Scene.CollidablePrims)
1472 return; 1831 return;
1473 1832
1474// m_log.DebugFormat( 1833 if (PhysicsShapeType == (byte)PhysShapeType.none)
1475// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 1834 return;
1476// Name, LocalId, UUID, m_physicalPrim);
1477 1835
1478 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 1836 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0;
1479 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 1837 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0;
1480 1838
1839
1481 if (IsJoint()) 1840 if (IsJoint())
1482 { 1841 {
1483 DoPhysicsPropertyUpdate(isPhysical, true); 1842 DoPhysicsPropertyUpdate(isPhysical, true);
@@ -1485,16 +1844,19 @@ namespace OpenSim.Region.Framework.Scenes
1485 else 1844 else
1486 { 1845 {
1487 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 1846 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored
1488 if (VolumeDetectActive) 1847// if (VolumeDetectActive)
1489 isPhantom = false; 1848// isPhantom = false;
1490 1849
1491 // Added clarification.. since A rigid body is an object that you can kick around, etc. 1850 // Added clarification.. since A rigid body is an object that you can kick around, etc.
1492 bool RigidBody = isPhysical && !isPhantom; 1851// bool RigidBody = isPhysical && !isPhantom;
1493 1852
1494 // 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 1853 // 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
1495 // or flexible 1854 // or flexible
1496 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible)) 1855 // if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1856 if ((!isPhantom || isPhysical || VolumeDetectActive) && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1497 { 1857 {
1858 Vector3 velocity = Velocity;
1859 Vector3 rotationalVelocity = AngularVelocity;
1498 try 1860 try
1499 { 1861 {
1500 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape( 1862 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
@@ -1502,8 +1864,10 @@ namespace OpenSim.Region.Framework.Scenes
1502 Shape, 1864 Shape,
1503 AbsolutePosition, 1865 AbsolutePosition,
1504 Scale, 1866 Scale,
1505 RotationOffset, 1867 GetWorldRotation(),
1506 RigidBody, 1868 isPhysical,
1869 isPhantom,
1870 PhysicsShapeType,
1507 m_localId); 1871 m_localId);
1508 } 1872 }
1509 catch 1873 catch
@@ -1519,8 +1883,30 @@ namespace OpenSim.Region.Framework.Scenes
1519 { 1883 {
1520 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 1884 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
1521 pa.SetMaterial(Material); 1885 pa.SetMaterial(Material);
1522 DoPhysicsPropertyUpdate(RigidBody, true); 1886
1523 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0); 1887 // if root part apply vehicle
1888 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
1889 m_vehicle.SetVehicle(pa);
1890
1891 DoPhysicsPropertyUpdate(isPhysical, true);
1892 if(VolumeDetectActive) // change if not the default only
1893 pa.SetVolumeDetect(1);
1894
1895 if (!building)
1896 pa.Building = false;
1897
1898 Velocity = velocity;
1899 AngularVelocity = rotationalVelocity;
1900 pa.Velocity = velocity;
1901 pa.RotationalVelocity = rotationalVelocity;
1902
1903 // if not vehicle and root part apply force and torque
1904 if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
1905 && LocalId == ParentGroup.RootPart.LocalId)
1906 {
1907 pa.Force = Force;
1908 pa.Torque = Torque;
1909 }
1524 } 1910 }
1525 } 1911 }
1526 } 1912 }
@@ -1574,6 +1960,11 @@ namespace OpenSim.Region.Framework.Scenes
1574 dupe.Category = Category; 1960 dupe.Category = Category;
1575 dupe.m_rezzed = m_rezzed; 1961 dupe.m_rezzed = m_rezzed;
1576 1962
1963 dupe.m_UndoRedo = null;
1964
1965 dupe.IgnoreUndoUpdate = false;
1966 dupe.Undoing = false;
1967
1577 dupe.m_inventory = new SceneObjectPartInventory(dupe); 1968 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1578 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 1969 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1579 1970
@@ -1589,6 +1980,7 @@ namespace OpenSim.Region.Framework.Scenes
1589 1980
1590 // Move afterwards ResetIDs as it clears the localID 1981 // Move afterwards ResetIDs as it clears the localID
1591 dupe.LocalId = localID; 1982 dupe.LocalId = localID;
1983
1592 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1984 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1593 dupe.LastOwnerID = OwnerID; 1985 dupe.LastOwnerID = OwnerID;
1594 1986
@@ -1608,6 +2000,9 @@ namespace OpenSim.Region.Framework.Scenes
1608 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2000 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
1609 } 2001 }
1610 2002
2003 if (dupe.PhysActor != null)
2004 dupe.PhysActor.LocalID = localID;
2005
1611 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2006 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1612 2007
1613// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2008// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1749,45 +2144,47 @@ namespace OpenSim.Region.Framework.Scenes
1749 { 2144 {
1750 if (pa.IsPhysical) // implies UsePhysics==false for this block 2145 if (pa.IsPhysical) // implies UsePhysics==false for this block
1751 { 2146 {
1752 if (!isNew) 2147 if (!isNew) // implies UsePhysics==false for this block
2148 {
1753 ParentGroup.Scene.RemovePhysicalPrim(1); 2149 ParentGroup.Scene.RemovePhysicalPrim(1);
1754 2150
1755 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2151 Velocity = new Vector3(0, 0, 0);
1756 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2152 Acceleration = new Vector3(0, 0, 0);
1757 pa.delink(); 2153 if (ParentGroup.RootPart == this)
2154 AngularVelocity = new Vector3(0, 0, 0);
1758 2155
1759 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2156 if (PhysActor.Phantom)
1760 { 2157 {
1761 // destroy all joints connected to this now deactivated body 2158 RemoveFromPhysics();
1762 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2159 return;
1763 } 2160 }
1764 2161
1765 // stop client-side interpolation of all joint proxy objects that have just been deleted 2162 PhysActor.IsPhysical = UsePhysics;
1766 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2163 PhysActor.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1767 // which stops client-side interpolation of deactivated joint proxy objects. 2164 PhysActor.OnOutOfBounds -= PhysicsOutOfBounds;
2165 PhysActor.delink();
2166 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2167 {
2168 // destroy all joints connected to this now deactivated body
2169 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(PhysActor);
2170 }
2171 }
1768 } 2172 }
1769 2173
1770 if (!UsePhysics && !isNew) 2174 if (PhysActor.IsPhysical != UsePhysics)
1771 { 2175 PhysActor.IsPhysical = UsePhysics;
1772 // reset velocity to 0 on physics switch-off. Without that, the client thinks the
1773 // prim still has velocity and continues to interpolate its position along the old
1774 // velocity-vector.
1775 Velocity = new Vector3(0, 0, 0);
1776 Acceleration = new Vector3(0, 0, 0);
1777 AngularVelocity = new Vector3(0, 0, 0);
1778 //RotationalVelocity = new Vector3(0, 0, 0);
1779 }
1780 2176
1781 pa.IsPhysical = UsePhysics; 2177 if (UsePhysics)
2178 {
2179 if (ParentGroup.RootPart.KeyframeMotion != null)
2180 ParentGroup.RootPart.KeyframeMotion.Stop();
2181 ParentGroup.RootPart.KeyframeMotion = null;
2182 ParentGroup.Scene.AddPhysicalPrim(1);
1782 2183
1783 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2184 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1784 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2185 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1785 /// that's not wholesome. Had to make Scene public
1786 //PhysActor = null;
1787 2186
1788 if ((Flags & PrimFlags.Phantom) == 0) 2187 if (ParentID != 0 && ParentID != LocalId)
1789 {
1790 if (UsePhysics)
1791 { 2188 {
1792 ParentGroup.Scene.AddPhysicalPrim(1); 2189 ParentGroup.Scene.AddPhysicalPrim(1);
1793 2190
@@ -1803,9 +2200,14 @@ namespace OpenSim.Region.Framework.Scenes
1803 } 2200 }
1804 } 2201 }
1805 } 2202 }
1806 } 2203 }
1807 } 2204 }
1808 2205
2206 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2207 if (PhysActor.Phantom != phan)
2208 PhysActor.Phantom = phan;
2209
2210
1809 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2211 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
1810 // mesh data. 2212 // mesh data.
1811 if (Shape.SculptEntry) 2213 if (Shape.SculptEntry)
@@ -1942,12 +2344,7 @@ namespace OpenSim.Region.Framework.Scenes
1942 2344
1943 public Vector3 GetForce() 2345 public Vector3 GetForce()
1944 { 2346 {
1945 PhysicsActor pa = PhysActor; 2347 return Force;
1946
1947 if (pa != null)
1948 return pa.Force;
1949 else
1950 return Vector3.Zero;
1951 } 2348 }
1952 2349
1953 /// <summary> 2350 /// <summary>
@@ -2583,9 +2980,9 @@ namespace OpenSim.Region.Framework.Scenes
2583 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2980 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2584 2981
2585 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2982 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2586 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2983 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2587 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2984 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2588 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2985 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2589 { 2986 {
2590 ParentGroup.AbsolutePosition = newpos; 2987 ParentGroup.AbsolutePosition = newpos;
2591 return; 2988 return;
@@ -2607,17 +3004,18 @@ namespace OpenSim.Region.Framework.Scenes
2607 //Trys to fetch sound id from prim's inventory. 3004 //Trys to fetch sound id from prim's inventory.
2608 //Prim's inventory doesn't support non script items yet 3005 //Prim's inventory doesn't support non script items yet
2609 3006
2610 lock (TaskInventory) 3007 TaskInventory.LockItemsForRead(true);
3008
3009 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2611 { 3010 {
2612 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3011 if (item.Value.Name == sound)
2613 { 3012 {
2614 if (item.Value.Name == sound) 3013 soundID = item.Value.ItemID;
2615 { 3014 break;
2616 soundID = item.Value.ItemID;
2617 break;
2618 }
2619 } 3015 }
2620 } 3016 }
3017
3018 TaskInventory.LockItemsForRead(false);
2621 } 3019 }
2622 3020
2623 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 3021 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2740,6 +3138,19 @@ namespace OpenSim.Region.Framework.Scenes
2740 APIDTarget = Quaternion.Identity; 3138 APIDTarget = Quaternion.Identity;
2741 } 3139 }
2742 3140
3141
3142
3143 public void ScheduleFullUpdateIfNone()
3144 {
3145 if (ParentGroup == null)
3146 return;
3147
3148// ??? ParentGroup.HasGroupChanged = true;
3149
3150 if (UpdateFlag != UpdateRequired.FULL)
3151 ScheduleFullUpdate();
3152 }
3153
2743 /// <summary> 3154 /// <summary>
2744 /// Schedules this prim for a full update 3155 /// Schedules this prim for a full update
2745 /// </summary> 3156 /// </summary>
@@ -2941,8 +3352,8 @@ namespace OpenSim.Region.Framework.Scenes
2941 { 3352 {
2942 const float ROTATION_TOLERANCE = 0.01f; 3353 const float ROTATION_TOLERANCE = 0.01f;
2943 const float VELOCITY_TOLERANCE = 0.001f; 3354 const float VELOCITY_TOLERANCE = 0.001f;
2944 const float POSITION_TOLERANCE = 0.05f; 3355 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2945 const int TIME_MS_TOLERANCE = 3000; 3356 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2946 3357
2947 switch (UpdateFlag) 3358 switch (UpdateFlag)
2948 { 3359 {
@@ -3004,17 +3415,16 @@ namespace OpenSim.Region.Framework.Scenes
3004 if (!UUID.TryParse(sound, out soundID)) 3415 if (!UUID.TryParse(sound, out soundID))
3005 { 3416 {
3006 // search sound file from inventory 3417 // search sound file from inventory
3007 lock (TaskInventory) 3418 TaskInventory.LockItemsForRead(true);
3419 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
3008 { 3420 {
3009 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3421 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
3010 { 3422 {
3011 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3423 soundID = item.Value.ItemID;
3012 { 3424 break;
3013 soundID = item.Value.ItemID;
3014 break;
3015 }
3016 } 3425 }
3017 } 3426 }
3427 TaskInventory.LockItemsForRead(false);
3018 } 3428 }
3019 3429
3020 if (soundID == UUID.Zero) 3430 if (soundID == UUID.Zero)
@@ -3099,10 +3509,13 @@ namespace OpenSim.Region.Framework.Scenes
3099 3509
3100 public void SetBuoyancy(float fvalue) 3510 public void SetBuoyancy(float fvalue)
3101 { 3511 {
3102 PhysicsActor pa = PhysActor; 3512 Buoyancy = fvalue;
3103 3513/*
3104 if (pa != null) 3514 if (PhysActor != null)
3105 pa.Buoyancy = fvalue; 3515 {
3516 PhysActor.Buoyancy = fvalue;
3517 }
3518 */
3106 } 3519 }
3107 3520
3108 public void SetDieAtEdge(bool p) 3521 public void SetDieAtEdge(bool p)
@@ -3123,42 +3536,112 @@ namespace OpenSim.Region.Framework.Scenes
3123 3536
3124 public void SetForce(Vector3 force) 3537 public void SetForce(Vector3 force)
3125 { 3538 {
3126 PhysicsActor pa = PhysActor; 3539 Force = force;
3540/*
3541 if (PhysActor != null)
3542 {
3543 PhysActor.Force = force;
3544 }
3545 */
3546 }
3127 3547
3128 if (pa != null) 3548 public SOPVehicle sopVehicle
3129 pa.Force = force; 3549 {
3550 get
3551 {
3552 return m_vehicle;
3553 }
3554 set
3555 {
3556 m_vehicle = value;
3557 }
3558 }
3559
3560
3561 public int VehicleType
3562 {
3563 get
3564 {
3565 if (m_vehicle == null)
3566 return (int)Vehicle.TYPE_NONE;
3567 else
3568 return (int)m_vehicle.Type;
3569 }
3570 set
3571 {
3572 SetVehicleType(value);
3573 }
3130 } 3574 }
3131 3575
3132 public void SetVehicleType(int type) 3576 public void SetVehicleType(int type)
3133 { 3577 {
3134 PhysicsActor pa = PhysActor; 3578 m_vehicle = null;
3579
3580 if (type == (int)Vehicle.TYPE_NONE)
3581 {
3582 if (_parentID ==0 && PhysActor != null)
3583 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3584 return;
3585 }
3586 m_vehicle = new SOPVehicle();
3587 m_vehicle.ProcessTypeChange((Vehicle)type);
3588 {
3589 if (_parentID ==0 && PhysActor != null)
3590 PhysActor.VehicleType = type;
3591 return;
3592 }
3593 }
3135 3594
3136 if (pa != null) 3595 public void SetVehicleFlags(int param, bool remove)
3137 pa.VehicleType = type; 3596 {
3597 if (m_vehicle == null)
3598 return;
3599
3600 m_vehicle.ProcessVehicleFlags(param, remove);
3601
3602 if (_parentID ==0 && PhysActor != null)
3603 {
3604 PhysActor.VehicleFlags(param, remove);
3605 }
3138 } 3606 }
3139 3607
3140 public void SetVehicleFloatParam(int param, float value) 3608 public void SetVehicleFloatParam(int param, float value)
3141 { 3609 {
3142 PhysicsActor pa = PhysActor; 3610 if (m_vehicle == null)
3611 return;
3143 3612
3144 if (pa != null) 3613 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
3145 pa.VehicleFloatParam(param, value); 3614
3615 if (_parentID == 0 && PhysActor != null)
3616 {
3617 PhysActor.VehicleFloatParam(param, value);
3618 }
3146 } 3619 }
3147 3620
3148 public void SetVehicleVectorParam(int param, Vector3 value) 3621 public void SetVehicleVectorParam(int param, Vector3 value)
3149 { 3622 {
3150 PhysicsActor pa = PhysActor; 3623 if (m_vehicle == null)
3624 return;
3151 3625
3152 if (pa != null) 3626 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
3153 pa.VehicleVectorParam(param, value); 3627
3628 if (_parentID == 0 && PhysActor != null)
3629 {
3630 PhysActor.VehicleVectorParam(param, value);
3631 }
3154 } 3632 }
3155 3633
3156 public void SetVehicleRotationParam(int param, Quaternion rotation) 3634 public void SetVehicleRotationParam(int param, Quaternion rotation)
3157 { 3635 {
3158 PhysicsActor pa = PhysActor; 3636 if (m_vehicle == null)
3637 return;
3159 3638
3160 if (pa != null) 3639 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
3161 pa.VehicleRotationParam(param, rotation); 3640
3641 if (_parentID == 0 && PhysActor != null)
3642 {
3643 PhysActor.VehicleRotationParam(param, rotation);
3644 }
3162 } 3645 }
3163 3646
3164 /// <summary> 3647 /// <summary>
@@ -3342,13 +3825,6 @@ namespace OpenSim.Region.Framework.Scenes
3342 hasProfileCut = hasDimple; // is it the same thing? 3825 hasProfileCut = hasDimple; // is it the same thing?
3343 } 3826 }
3344 3827
3345 public void SetVehicleFlags(int param, bool remove)
3346 {
3347 if (PhysActor != null)
3348 {
3349 PhysActor.VehicleFlags(param, remove);
3350 }
3351 }
3352 3828
3353 public void SetGroup(UUID groupID, IClientAPI client) 3829 public void SetGroup(UUID groupID, IClientAPI client)
3354 { 3830 {
@@ -3451,68 +3927,18 @@ namespace OpenSim.Region.Framework.Scenes
3451 //ParentGroup.ScheduleGroupForFullUpdate(); 3927 //ParentGroup.ScheduleGroupForFullUpdate();
3452 } 3928 }
3453 3929
3454 public void StoreUndoState() 3930 public void StoreUndoState(ObjectChangeType change)
3455 { 3931 {
3456 StoreUndoState(false); 3932 if (m_UndoRedo == null)
3457 } 3933 m_UndoRedo = new UndoRedoState(5);
3458 3934
3459 public void StoreUndoState(bool forGroup) 3935 lock (m_UndoRedo)
3460 {
3461 if (!Undoing)
3462 { 3936 {
3463 if (!IgnoreUndoUpdate) 3937 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3464 { 3938 {
3465 if (ParentGroup != null) 3939 m_UndoRedo.StoreUndo(this, change);
3466 {
3467 lock (m_undo)
3468 {
3469 if (m_undo.Count > 0)
3470 {
3471 UndoState last = m_undo.Peek();
3472 if (last != null)
3473 {
3474 // TODO: May need to fix for group comparison
3475 if (last.Compare(this))
3476 {
3477 // m_log.DebugFormat(
3478 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3479 // Name, LocalId, m_undo.Count);
3480
3481 return;
3482 }
3483 }
3484 }
3485
3486 // m_log.DebugFormat(
3487 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3488 // Name, LocalId, forGroup, m_undo.Count);
3489
3490 if (ParentGroup.GetSceneMaxUndo() > 0)
3491 {
3492 UndoState nUndo = new UndoState(this, forGroup);
3493
3494 m_undo.Push(nUndo);
3495
3496 if (m_redo.Count > 0)
3497 m_redo.Clear();
3498
3499 // m_log.DebugFormat(
3500 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3501 // Name, LocalId, forGroup, m_undo.Count);
3502 }
3503 }
3504 }
3505 } 3940 }
3506// else
3507// {
3508// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3509// }
3510 } 3941 }
3511// else
3512// {
3513// m_log.DebugFormat(
3514// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3515// }
3516 } 3942 }
3517 3943
3518 /// <summary> 3944 /// <summary>
@@ -3522,84 +3948,46 @@ namespace OpenSim.Region.Framework.Scenes
3522 { 3948 {
3523 get 3949 get
3524 { 3950 {
3525 lock (m_undo) 3951 if (m_UndoRedo == null)
3526 return m_undo.Count; 3952 return 0;
3953 return m_UndoRedo.Count;
3527 } 3954 }
3528 } 3955 }
3529 3956
3530 public void Undo() 3957 public void Undo()
3531 { 3958 {
3532 lock (m_undo) 3959 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3533 { 3960 return;
3534// m_log.DebugFormat(
3535// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3536// Name, LocalId, m_undo.Count);
3537
3538 if (m_undo.Count > 0)
3539 {
3540 UndoState goback = m_undo.Pop();
3541
3542 if (goback != null)
3543 {
3544 UndoState nUndo = null;
3545
3546 if (ParentGroup.GetSceneMaxUndo() > 0)
3547 {
3548 nUndo = new UndoState(this, goback.ForGroup);
3549 }
3550
3551 goback.PlaybackState(this);
3552
3553 if (nUndo != null)
3554 m_redo.Push(nUndo);
3555 }
3556 }
3557 3961
3558// m_log.DebugFormat( 3962 lock (m_UndoRedo)
3559// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3963 {
3560// Name, LocalId, m_undo.Count); 3964 Undoing = true;
3965 m_UndoRedo.Undo(this);
3966 Undoing = false;
3561 } 3967 }
3562 } 3968 }
3563 3969
3564 public void Redo() 3970 public void Redo()
3565 { 3971 {
3566 lock (m_undo) 3972 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3567 { 3973 return;
3568// m_log.DebugFormat(
3569// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3570// Name, LocalId, m_redo.Count);
3571
3572 if (m_redo.Count > 0)
3573 {
3574 UndoState gofwd = m_redo.Pop();
3575
3576 if (gofwd != null)
3577 {
3578 if (ParentGroup.GetSceneMaxUndo() > 0)
3579 {
3580 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3581
3582 m_undo.Push(nUndo);
3583 }
3584
3585 gofwd.PlayfwdState(this);
3586 }
3587 3974
3588// m_log.DebugFormat( 3975 lock (m_UndoRedo)
3589// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3976 {
3590// Name, LocalId, m_redo.Count); 3977 Undoing = true;
3591 } 3978 m_UndoRedo.Redo(this);
3979 Undoing = false;
3592 } 3980 }
3593 } 3981 }
3594 3982
3595 public void ClearUndoState() 3983 public void ClearUndoState()
3596 { 3984 {
3597// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3985 if (m_UndoRedo == null || Undoing)
3986 return;
3598 3987
3599 lock (m_undo) 3988 lock (m_UndoRedo)
3600 { 3989 {
3601 m_undo.Clear(); 3990 m_UndoRedo.Clear();
3602 m_redo.Clear();
3603 } 3991 }
3604 } 3992 }
3605 3993
@@ -4229,6 +4617,27 @@ namespace OpenSim.Region.Framework.Scenes
4229 } 4617 }
4230 } 4618 }
4231 4619
4620
4621 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4622 {
4623 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4624 return;
4625
4626 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4627 {
4628 PhysicsShapeType = (byte)physdata.PhysShapeType;
4629
4630 }
4631
4632 if(Density != physdata.Density)
4633 Density = physdata.Density;
4634 if(GravityModifier != physdata.GravitationModifier)
4635 GravityModifier = physdata.GravitationModifier;
4636 if(Friction != physdata.Friction)
4637 Friction = physdata.Friction;
4638 if(Bounciness != physdata.Bounce)
4639 Bounciness = physdata.Bounce;
4640 }
4232 /// <summary> 4641 /// <summary>
4233 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4642 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
4234 /// </summary> 4643 /// </summary>
@@ -4236,7 +4645,8 @@ namespace OpenSim.Region.Framework.Scenes
4236 /// <param name="SetTemporary"></param> 4645 /// <param name="SetTemporary"></param>
4237 /// <param name="SetPhantom"></param> 4646 /// <param name="SetPhantom"></param>
4238 /// <param name="SetVD"></param> 4647 /// <param name="SetVD"></param>
4239 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4648// public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD)
4649 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
4240 { 4650 {
4241 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4651 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
4242 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4652 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -4246,44 +4656,58 @@ namespace OpenSim.Region.Framework.Scenes
4246 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4656 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
4247 return; 4657 return;
4248 4658
4249 PhysicsActor pa = PhysActor; 4659 // do this first
4660 if (building && PhysActor != null && PhysActor.Building != building)
4661 PhysActor.Building = building;
4250 4662
4251 // Special cases for VD. VD can only be called from a script 4663 // Special cases for VD. VD can only be called from a script
4252 // and can't be combined with changes to other states. So we can rely 4664 // and can't be combined with changes to other states. So we can rely
4253 // that... 4665 // that...
4254 // ... if VD is changed, all others are not. 4666 // ... if VD is changed, all others are not.
4255 // ... if one of the others is changed, VD is not. 4667 // ... if one of the others is changed, VD is not.
4668
4669/*
4256 if (SetVD) // VD is active, special logic applies 4670 if (SetVD) // VD is active, special logic applies
4257 {
4258 // State machine logic for VolumeDetect
4259 // More logic below
4260 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4261 4671
4262 if (phanReset) // Phantom changes from on to off switch VD off too 4672 volume detection is now independent of phantom in sl
4263 {
4264 SetVD = false; // Switch it of for the course of this routine
4265 VolumeDetectActive = false; // and also permanently
4266 4673
4267 if (pa != null) 4674 {
4268 pa.SetVolumeDetect(0); // Let physics know about it too 4675 // State machine logic for VolumeDetect
4269 } 4676 // More logic below
4270 else 4677
4271 { 4678
4272 // If volumedetect is active we don't want phantom to be applied. 4679 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
4273 // If this is a new call to VD out of the state "phantom" 4680
4274 // this will also cause the prim to be visible to physics 4681 if (phanReset) // Phantom changes from on to off switch VD off too
4682 {
4683 SetVD = false; // Switch it of for the course of this routine
4684 VolumeDetectActive = false; // and also permanently
4685 if (PhysActor != null)
4686 PhysActor.SetVolumeDetect(0); // Let physics know about it too
4687 }
4688 else
4689 {
4690 // If volumedetect is active we don't want phantom to be applied.
4691 // If this is a new call to VD out of the state "phantom"
4692 // this will also cause the prim to be visible to physics
4275 SetPhantom = false; 4693 SetPhantom = false;
4276 } 4694 }
4695 }
4696 else if (wasVD)
4697 {
4698 // Correspondingly, if VD is turned off, also turn off phantom
4699 SetPhantom = false;
4277 } 4700 }
4278 4701
4279 if (UsePhysics && IsJoint()) 4702 if (UsePhysics && IsJoint())
4280 { 4703 {
4281 SetPhantom = true; 4704 SetPhantom = true;
4282 } 4705 }
4283 4706*/
4284 if (UsePhysics) 4707 if (UsePhysics)
4285 { 4708 {
4286 AddFlag(PrimFlags.Physics); 4709 AddFlag(PrimFlags.Physics);
4710/*
4287 if (!wasUsingPhysics) 4711 if (!wasUsingPhysics)
4288 { 4712 {
4289 DoPhysicsPropertyUpdate(UsePhysics, false); 4713 DoPhysicsPropertyUpdate(UsePhysics, false);
@@ -4296,83 +4720,106 @@ namespace OpenSim.Region.Framework.Scenes
4296 } 4720 }
4297 } 4721 }
4298 } 4722 }
4723 */
4299 } 4724 }
4300 else 4725 else
4301 { 4726 {
4302 RemFlag(PrimFlags.Physics); 4727 RemFlag(PrimFlags.Physics);
4728/*
4303 if (wasUsingPhysics) 4729 if (wasUsingPhysics)
4304 { 4730 {
4305 DoPhysicsPropertyUpdate(UsePhysics, false); 4731 DoPhysicsPropertyUpdate(UsePhysics, false);
4306 } 4732 }
4307 } 4733*/
4734 }
4308 4735
4309 if (SetPhantom 4736 if (SetPhantom)
4310 || ParentGroup.IsAttachment 4737 AddFlag(PrimFlags.Phantom);
4738 else
4739 RemFlag(PrimFlags.Phantom);
4740
4741 if ((SetPhantom && !UsePhysics) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4311 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints 4742 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
4312 { 4743 {
4313 AddFlag(PrimFlags.Phantom); 4744// AddFlag(PrimFlags.Phantom);
4745
4746 Velocity = new Vector3(0, 0, 0);
4747 Acceleration = new Vector3(0, 0, 0);
4748 if (ParentGroup.RootPart == this)
4749 AngularVelocity = new Vector3(0, 0, 0);
4314 4750
4315 if (PhysActor != null) 4751 if (PhysActor != null)
4752 {
4753 ParentGroup.Scene.RemovePhysicalPrim(1);
4316 RemoveFromPhysics(); 4754 RemoveFromPhysics();
4755 }
4317 } 4756 }
4318 else // Not phantom 4757 else
4319 { 4758 {
4320 RemFlag(PrimFlags.Phantom);
4321
4322 if (ParentGroup.Scene == null) 4759 if (ParentGroup.Scene == null)
4323 return; 4760 return;
4324 4761
4325 if (ParentGroup.Scene.CollidablePrims && PhysActor == null) 4762 if (ParentGroup.Scene.CollidablePrims)
4326 { 4763 {
4327 // It's not phantom anymore. So make sure the physics engine get's knowledge of it 4764 if (PhysActor == null)
4328 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4329 string.Format("{0}/{1}", Name, UUID),
4330 Shape,
4331 AbsolutePosition,
4332 Scale,
4333 RotationOffset,
4334 UsePhysics,
4335 m_localId);
4336
4337 PhysActor.SetMaterial(Material);
4338 DoPhysicsPropertyUpdate(UsePhysics, true);
4339
4340 if (!ParentGroup.IsDeleted)
4341 { 4765 {
4342 if (LocalId == ParentGroup.RootPart.LocalId) 4766 PhysActor = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4767 string.Format("{0}/{1}", Name, UUID),
4768 Shape,
4769 AbsolutePosition,
4770 Scale,
4771 GetWorldRotation(), //physics wants world rotation like all other functions send
4772 UsePhysics,
4773 SetPhantom,
4774 PhysicsShapeType,
4775 m_localId);
4776
4777 PhysActor.SetMaterial(Material);
4778
4779 // if root part apply vehicle
4780 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
4781 m_vehicle.SetVehicle(PhysActor);
4782
4783 DoPhysicsPropertyUpdate(UsePhysics, true);
4784
4785 if (!ParentGroup.IsDeleted)
4343 { 4786 {
4344 ParentGroup.CheckSculptAndLoad(); 4787 if (LocalId == ParentGroup.RootPart.LocalId)
4788 {
4789 ParentGroup.CheckSculptAndLoad();
4790 }
4345 } 4791 }
4346 }
4347 4792
4348 if ( 4793 if (
4349 ((AggregateScriptEvents & scriptEvents.collision) != 0) || 4794 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4350 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) || 4795 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4351 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) || 4796 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4352 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) || 4797 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4353 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) || 4798 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4354 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) || 4799 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4355 (CollisionSound != UUID.Zero) 4800 (CollisionSound != UUID.Zero)
4356 ) 4801 )
4357 { 4802 {
4358 PhysActor.OnCollisionUpdate += PhysicsCollision; 4803 PhysActor.OnCollisionUpdate += PhysicsCollision;
4359 PhysActor.SubscribeEvents(1000); 4804 PhysActor.SubscribeEvents(1000);
4805 }
4360 } 4806 }
4361 } 4807 else // it already has a physical representation
4362 else // it already has a physical representation
4363 {
4364 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4365
4366 if (!ParentGroup.IsDeleted)
4367 { 4808 {
4368 if (LocalId == ParentGroup.RootPart.LocalId) 4809 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4810
4811 if (!ParentGroup.IsDeleted)
4369 { 4812 {
4370 ParentGroup.CheckSculptAndLoad(); 4813 if (LocalId == ParentGroup.RootPart.LocalId)
4814 {
4815 ParentGroup.CheckSculptAndLoad();
4816 }
4371 } 4817 }
4372 } 4818 }
4373 } 4819 }
4374 } 4820 }
4375 4821
4822 PhysicsActor pa = PhysActor;
4376 if (SetVD) 4823 if (SetVD)
4377 { 4824 {
4378 // If the above logic worked (this is urgent candidate to unit tests!) 4825 // If the above logic worked (this is urgent candidate to unit tests!)
@@ -4383,7 +4830,7 @@ namespace OpenSim.Region.Framework.Scenes
4383 if (pa != null) 4830 if (pa != null)
4384 { 4831 {
4385 pa.SetVolumeDetect(1); 4832 pa.SetVolumeDetect(1);
4386 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4833// AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active
4387 this.VolumeDetectActive = true; 4834 this.VolumeDetectActive = true;
4388 } 4835 }
4389 } 4836 }
@@ -4392,9 +4839,10 @@ namespace OpenSim.Region.Framework.Scenes
4392 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4839 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like
4393 // (mumbles, well, at least if you have infinte CPU powers :-)) 4840 // (mumbles, well, at least if you have infinte CPU powers :-))
4394 if (pa != null) 4841 if (pa != null)
4395 PhysActor.SetVolumeDetect(0); 4842 {
4396 4843 pa.SetVolumeDetect(0);
4397 this.VolumeDetectActive = false; 4844 this.VolumeDetectActive = false;
4845 }
4398 } 4846 }
4399 4847
4400 if (SetTemporary) 4848 if (SetTemporary)
@@ -4408,12 +4856,15 @@ namespace OpenSim.Region.Framework.Scenes
4408 4856
4409 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4857 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4410 4858
4859 // and last in case we have a new actor and not building
4860 if (pa != null && pa.Building != building)
4861 pa.Building = building;
4411 if (ParentGroup != null) 4862 if (ParentGroup != null)
4412 { 4863 {
4413 ParentGroup.HasGroupChanged = true; 4864 ParentGroup.HasGroupChanged = true;
4414 ScheduleFullUpdate(); 4865 ScheduleFullUpdate();
4415 } 4866 }
4416 4867
4417// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4868// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4418 } 4869 }
4419 4870
@@ -4775,5 +5226,17 @@ namespace OpenSim.Region.Framework.Scenes
4775 Color color = Color; 5226 Color color = Color;
4776 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5227 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4777 } 5228 }
5229
5230 public void ResetOwnerChangeFlag()
5231 {
5232 List<UUID> inv = Inventory.GetInventoryList();
5233
5234 foreach (UUID itemID in inv)
5235 {
5236 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5237 item.OwnerChanged = false;
5238 Inventory.UpdateInventoryItem(item, false, false);
5239 }
5240 }
4778 } 5241 }
4779} 5242}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index f7e123b..a2649ee 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 List<TaskInventoryItem> items = new List<TaskInventoryItem>(); 783 List<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.GetPart(group.UUID); 818 SceneObjectPart rootPart = group.GetPart(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 19dab32..ed3a7f1 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Scenes
92 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 92 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
93 /// issue #1716 93 /// issue #1716
94 /// </summary> 94 /// </summary>
95 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); 95 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
96 96
97 /// <summary> 97 /// <summary>
98 /// Movement updates for agents in neighboring regions are sent directly to clients. 98 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -169,6 +169,7 @@ namespace OpenSim.Region.Framework.Scenes
169// private int m_lastColCount = -1; //KF: Look for Collision chnages 169// private int m_lastColCount = -1; //KF: Look for Collision chnages
170// private int m_updateCount = 0; //KF: Update Anims for a while 170// private int m_updateCount = 0; //KF: Update Anims for a while
171// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 171// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
172 private List<uint> m_lastColliders = new List<uint>();
172 173
173 private TeleportFlags m_teleportFlags; 174 private TeleportFlags m_teleportFlags;
174 public TeleportFlags TeleportFlags 175 public TeleportFlags TeleportFlags
@@ -230,6 +231,13 @@ namespace OpenSim.Region.Framework.Scenes
230 //private int m_moveToPositionStateStatus; 231 //private int m_moveToPositionStateStatus;
231 //***************************************************** 232 //*****************************************************
232 233
234 private bool m_collisionEventFlag = false;
235 private object m_collisionEventLock = new Object();
236
237 private int m_movementAnimationUpdateCounter = 0;
238
239 private Vector3 m_prevSitOffset;
240
233 protected AvatarAppearance m_appearance; 241 protected AvatarAppearance m_appearance;
234 242
235 public AvatarAppearance Appearance 243 public AvatarAppearance Appearance
@@ -569,6 +577,13 @@ namespace OpenSim.Region.Framework.Scenes
569 /// </summary> 577 /// </summary>
570 public uint ParentID { get; set; } 578 public uint ParentID { get; set; }
571 579
580 public UUID ParentUUID
581 {
582 get { return m_parentUUID; }
583 set { m_parentUUID = value; }
584 }
585 private UUID m_parentUUID = UUID.Zero;
586
572 /// <summary> 587 /// <summary>
573 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null. 588 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
574 /// </summary> 589 /// </summary>
@@ -729,6 +744,26 @@ namespace OpenSim.Region.Framework.Scenes
729 Appearance = appearance; 744 Appearance = appearance;
730 } 745 }
731 746
747 private void RegionHeartbeatEnd(Scene scene)
748 {
749 if (IsChildAgent)
750 return;
751
752 m_movementAnimationUpdateCounter ++;
753 if (m_movementAnimationUpdateCounter >= 2)
754 {
755 m_movementAnimationUpdateCounter = 0;
756 if (Animator != null)
757 {
758 Animator.UpdateMovementAnimations();
759 }
760 else
761 {
762 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
763 }
764 }
765 }
766
732 public void RegisterToEvents() 767 public void RegisterToEvents()
733 { 768 {
734 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 769 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
@@ -798,10 +833,38 @@ namespace OpenSim.Region.Framework.Scenes
798 "[SCENE]: Upgrading child to root agent for {0} in {1}", 833 "[SCENE]: Upgrading child to root agent for {0} in {1}",
799 Name, m_scene.RegionInfo.RegionName); 834 Name, m_scene.RegionInfo.RegionName);
800 835
801 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
802
803 bool wasChild = IsChildAgent; 836 bool wasChild = IsChildAgent;
804 IsChildAgent = false; 837
838 if (ParentUUID != UUID.Zero)
839 {
840 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
841 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
842 if (part == null)
843 {
844 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
845 }
846 else
847 {
848 part.ParentGroup.AddAvatar(UUID);
849 if (part.SitTargetPosition != Vector3.Zero)
850 part.SitTargetAvatar = UUID;
851 ParentPosition = part.GetWorldPosition();
852 ParentID = part.LocalId;
853 ParentPart = part;
854 m_pos = m_prevSitOffset;
855 pos = ParentPosition;
856 }
857 ParentUUID = UUID.Zero;
858
859 IsChildAgent = false;
860
861 Animator.TrySetMovementAnimation("SIT");
862 }
863 else
864 {
865 IsChildAgent = false;
866 }
867
805 868
806 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 869 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
807 if (gm != null) 870 if (gm != null)
@@ -811,62 +874,64 @@ namespace OpenSim.Region.Framework.Scenes
811 874
812 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 875 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
813 876
814 // Moved this from SendInitialData to ensure that Appearance is initialized 877 if (ParentID == 0)
815 // before the inventory is processed in MakeRootAgent. This fixes a race condition
816 // related to the handling of attachments
817 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
818 if (m_scene.TestBorderCross(pos, Cardinals.E))
819 { 878 {
820 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 879 // Moved this from SendInitialData to ensure that Appearance is initialized
821 pos.X = crossedBorder.BorderLine.Z - 1; 880 // before the inventory is processed in MakeRootAgent. This fixes a race condition
822 } 881 // related to the handling of attachments
882 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
883 if (m_scene.TestBorderCross(pos, Cardinals.E))
884 {
885 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
886 pos.X = crossedBorder.BorderLine.Z - 1;
887 }
823 888
824 if (m_scene.TestBorderCross(pos, Cardinals.N)) 889 if (m_scene.TestBorderCross(pos, Cardinals.N))
825 { 890 {
826 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 891 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
827 pos.Y = crossedBorder.BorderLine.Z - 1; 892 pos.Y = crossedBorder.BorderLine.Z - 1;
828 } 893 }
829 894
830 CheckAndAdjustLandingPoint(ref pos); 895 CheckAndAdjustLandingPoint(ref pos);
831 896
832 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 897 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
833 { 898 {
834 m_log.WarnFormat( 899 m_log.WarnFormat(
835 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 900 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
836 pos, Name, UUID); 901 pos, Name, UUID);
837 902
838 if (pos.X < 0f) pos.X = 0f; 903 if (pos.X < 0f) pos.X = 0f;
839 if (pos.Y < 0f) pos.Y = 0f; 904 if (pos.Y < 0f) pos.Y = 0f;
840 if (pos.Z < 0f) pos.Z = 0f; 905 if (pos.Z < 0f) pos.Z = 0f;
841 } 906 }
842 907
843 float localAVHeight = 1.56f; 908 float localAVHeight = 1.56f;
844 if (Appearance.AvatarHeight > 0) 909 if (Appearance.AvatarHeight > 0)
845 localAVHeight = Appearance.AvatarHeight; 910 localAVHeight = Appearance.AvatarHeight;
846 911
847 float posZLimit = 0; 912 float posZLimit = 0;
848 913
849 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 914 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
850 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 915 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
851 916
852 float newPosZ = posZLimit + localAVHeight / 2; 917 float newPosZ = posZLimit + localAVHeight / 2;
853 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 918 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
854 { 919 {
855 pos.Z = newPosZ; 920 pos.Z = newPosZ;
856 } 921 }
857 AbsolutePosition = pos; 922 AbsolutePosition = pos;
858 923
859 AddToPhysicalScene(isFlying); 924 AddToPhysicalScene(isFlying);
860 925
861 if (ForceFly) 926 if (ForceFly)
862 { 927 {
863 Flying = true; 928 Flying = true;
864 } 929 }
865 else if (FlyDisabled) 930 else if (FlyDisabled)
866 { 931 {
867 Flying = false; 932 Flying = false;
933 }
868 } 934 }
869
870 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 935 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
871 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 936 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
872 // elsewhere anyway 937 // elsewhere anyway
@@ -884,14 +949,19 @@ namespace OpenSim.Region.Framework.Scenes
884 { 949 {
885 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 950 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
886 // Resume scripts 951 // Resume scripts
887 foreach (SceneObjectGroup sog in m_attachments) 952 Util.FireAndForget(delegate(object x) {
888 { 953 foreach (SceneObjectGroup sog in m_attachments)
889 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 954 {
890 sog.ResumeScripts(); 955 sog.ScheduleGroupForFullUpdate();
891 } 956 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
957 sog.ResumeScripts();
958 }
959 });
892 } 960 }
893 } 961 }
894 962
963 SendAvatarDataToAllAgents();
964
895 // send the animations of the other presences to me 965 // send the animations of the other presences to me
896 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) 966 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
897 { 967 {
@@ -905,6 +975,8 @@ namespace OpenSim.Region.Framework.Scenes
905 MovementFlag = 0; 975 MovementFlag = 0;
906 976
907 m_scene.EventManager.TriggerOnMakeRootAgent(this); 977 m_scene.EventManager.TriggerOnMakeRootAgent(this);
978
979 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
908 } 980 }
909 981
910 public int GetStateSource() 982 public int GetStateSource()
@@ -932,6 +1004,8 @@ namespace OpenSim.Region.Framework.Scenes
932 /// </remarks> 1004 /// </remarks>
933 public void MakeChildAgent() 1005 public void MakeChildAgent()
934 { 1006 {
1007 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1008
935 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1009 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName);
936 1010
937 // Reset these so that teleporting in and walking out isn't seen 1011 // Reset these so that teleporting in and walking out isn't seen
@@ -1689,9 +1763,9 @@ namespace OpenSim.Region.Framework.Scenes
1689 if (pos.Z - terrainHeight < 0.2) 1763 if (pos.Z - terrainHeight < 0.2)
1690 pos.Z = terrainHeight; 1764 pos.Z = terrainHeight;
1691 1765
1692 m_log.DebugFormat( 1766// m_log.DebugFormat(
1693 "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}", 1767// "[SCENE PRESENCE]: Avatar {0} set move to target {1} (terrain height {2}) in {3}",
1694 Name, pos, terrainHeight, m_scene.RegionInfo.RegionName); 1768// Name, pos, terrainHeight, m_scene.RegionInfo.RegionName);
1695 1769
1696 if (noFly) 1770 if (noFly)
1697 Flying = false; 1771 Flying = false;
@@ -1748,8 +1822,11 @@ namespace OpenSim.Region.Framework.Scenes
1748// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 1822// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
1749 1823
1750 SitGround = false; 1824 SitGround = false;
1825
1826/* move this down so avatar gets physical in the new position and not where it is siting
1751 if (PhysicsActor == null) 1827 if (PhysicsActor == null)
1752 AddToPhysicalScene(false); 1828 AddToPhysicalScene(false);
1829 */
1753 1830
1754 if (ParentID != 0) 1831 if (ParentID != 0)
1755 { 1832 {
@@ -1773,6 +1850,7 @@ namespace OpenSim.Region.Framework.Scenes
1773 if (part.SitTargetAvatar == UUID) 1850 if (part.SitTargetAvatar == UUID)
1774 part.SitTargetAvatar = UUID.Zero; 1851 part.SitTargetAvatar = UUID.Zero;
1775 1852
1853 part.ParentGroup.DeleteAvatar(UUID);
1776 ParentPosition = part.GetWorldPosition(); 1854 ParentPosition = part.GetWorldPosition();
1777 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1855 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1778 1856
@@ -1781,6 +1859,10 @@ namespace OpenSim.Region.Framework.Scenes
1781 1859
1782 ParentID = 0; 1860 ParentID = 0;
1783 ParentPart = null; 1861 ParentPart = null;
1862
1863 if (PhysicsActor == null)
1864 AddToPhysicalScene(false);
1865
1784 SendAvatarDataToAllAgents(); 1866 SendAvatarDataToAllAgents();
1785 m_requestedSitTargetID = 0; 1867 m_requestedSitTargetID = 0;
1786 1868
@@ -1788,6 +1870,9 @@ namespace OpenSim.Region.Framework.Scenes
1788 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 1870 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1789 } 1871 }
1790 1872
1873 else if (PhysicsActor == null)
1874 AddToPhysicalScene(false);
1875
1791 Animator.TrySetMovementAnimation("STAND"); 1876 Animator.TrySetMovementAnimation("STAND");
1792 } 1877 }
1793 1878
@@ -1911,7 +1996,7 @@ namespace OpenSim.Region.Framework.Scenes
1911 forceMouselook = part.GetForceMouselook(); 1996 forceMouselook = part.GetForceMouselook();
1912 1997
1913 ControllingClient.SendSitResponse( 1998 ControllingClient.SendSitResponse(
1914 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 1999 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1915 2000
1916 m_requestedSitTargetUUID = targetID; 2001 m_requestedSitTargetUUID = targetID;
1917 2002
@@ -2193,14 +2278,36 @@ namespace OpenSim.Region.Framework.Scenes
2193 2278
2194 //Quaternion result = (sitTargetOrient * vq) * nq; 2279 //Quaternion result = (sitTargetOrient * vq) * nq;
2195 2280
2196 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2281 double x, y, z, m;
2282
2283 Quaternion r = sitTargetOrient;
2284 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2285
2286 if (Math.Abs(1.0 - m) > 0.000001)
2287 {
2288 m = 1.0 / Math.Sqrt(m);
2289 r.X *= (float)m;
2290 r.Y *= (float)m;
2291 r.Z *= (float)m;
2292 r.W *= (float)m;
2293 }
2294
2295 x = 2 * (r.X * r.Z + r.Y * r.W);
2296 y = 2 * (-r.X * r.W + r.Y * r.Z);
2297 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2298
2299 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2300 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2301 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2197 Rotation = sitTargetOrient; 2302 Rotation = sitTargetOrient;
2198 ParentPosition = part.AbsolutePosition; 2303 ParentPosition = part.AbsolutePosition;
2304 part.ParentGroup.AddAvatar(UUID);
2199 } 2305 }
2200 else 2306 else
2201 { 2307 {
2202 m_pos -= part.AbsolutePosition; 2308 m_pos -= part.AbsolutePosition;
2203 ParentPosition = part.AbsolutePosition; 2309 ParentPosition = part.AbsolutePosition;
2310 part.ParentGroup.AddAvatar(UUID);
2204 2311
2205// m_log.DebugFormat( 2312// m_log.DebugFormat(
2206// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2313// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -2298,14 +2405,15 @@ namespace OpenSim.Region.Framework.Scenes
2298 direc.Z *= 2.6f; 2405 direc.Z *= 2.6f;
2299 2406
2300 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2407 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
2301 Animator.TrySetMovementAnimation("PREJUMP"); 2408// Animator.TrySetMovementAnimation("PREJUMP");
2302 Animator.TrySetMovementAnimation("JUMP"); 2409// Animator.TrySetMovementAnimation("JUMP");
2303 } 2410 }
2304 } 2411 }
2305 } 2412 }
2306 2413
2307 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2414 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2308 m_forceToApply = direc; 2415 m_forceToApply = direc;
2416 Animator.UpdateMovementAnimations();
2309 } 2417 }
2310 2418
2311 #endregion 2419 #endregion
@@ -3039,6 +3147,9 @@ namespace OpenSim.Region.Framework.Scenes
3039 cAgent.AlwaysRun = SetAlwaysRun; 3147 cAgent.AlwaysRun = SetAlwaysRun;
3040 3148
3041 cAgent.Appearance = new AvatarAppearance(Appearance); 3149 cAgent.Appearance = new AvatarAppearance(Appearance);
3150
3151 cAgent.ParentPart = ParentUUID;
3152 cAgent.SitOffset = m_pos;
3042 3153
3043 lock (scriptedcontrols) 3154 lock (scriptedcontrols)
3044 { 3155 {
@@ -3098,6 +3209,8 @@ namespace OpenSim.Region.Framework.Scenes
3098 CameraAtAxis = cAgent.AtAxis; 3209 CameraAtAxis = cAgent.AtAxis;
3099 CameraLeftAxis = cAgent.LeftAxis; 3210 CameraLeftAxis = cAgent.LeftAxis;
3100 CameraUpAxis = cAgent.UpAxis; 3211 CameraUpAxis = cAgent.UpAxis;
3212 ParentUUID = cAgent.ParentPart;
3213 m_prevSitOffset = cAgent.SitOffset;
3101 3214
3102 // When we get to the point of re-computing neighbors everytime this 3215 // When we get to the point of re-computing neighbors everytime this
3103 // changes, then start using the agent's drawdistance rather than the 3216 // changes, then start using the agent's drawdistance rather than the
@@ -3250,18 +3363,6 @@ namespace OpenSim.Region.Framework.Scenes
3250 if (IsChildAgent) 3363 if (IsChildAgent)
3251 return; 3364 return;
3252 3365
3253 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3254 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3255 // as of this comment the interval is set in AddToPhysicalScene
3256 if (Animator != null)
3257 {
3258// if (m_updateCount > 0)
3259// {
3260 Animator.UpdateMovementAnimations();
3261// m_updateCount--;
3262// }
3263 }
3264
3265 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3366 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3266 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3367 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3267 3368
@@ -3304,6 +3405,8 @@ namespace OpenSim.Region.Framework.Scenes
3304 } 3405 }
3305 } 3406 }
3306 3407
3408 RaiseCollisionScriptEvents(coldata);
3409
3307 if (Invulnerable) 3410 if (Invulnerable)
3308 return; 3411 return;
3309 3412
@@ -3815,6 +3918,12 @@ namespace OpenSim.Region.Framework.Scenes
3815 3918
3816 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 3919 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
3817 { 3920 {
3921 string reason;
3922
3923 // Honor bans
3924 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
3925 return;
3926
3818 SceneObjectGroup telehub = null; 3927 SceneObjectGroup telehub = null;
3819 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 3928 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
3820 { 3929 {
@@ -3854,11 +3963,173 @@ namespace OpenSim.Region.Framework.Scenes
3854 pos = land.LandData.UserLocation; 3963 pos = land.LandData.UserLocation;
3855 } 3964 }
3856 } 3965 }
3857 3966
3858 land.SendLandUpdateToClient(ControllingClient); 3967 land.SendLandUpdateToClient(ControllingClient);
3859 } 3968 }
3860 } 3969 }
3861 3970
3971 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
3972 {
3973 lock(m_collisionEventLock)
3974 {
3975 if (m_collisionEventFlag)
3976 return;
3977 m_collisionEventFlag = true;
3978 }
3979
3980 Util.FireAndForget(delegate(object x)
3981 {
3982 try
3983 {
3984 List<uint> thisHitColliders = new List<uint>();
3985 List<uint> endedColliders = new List<uint>();
3986 List<uint> startedColliders = new List<uint>();
3987
3988 foreach (uint localid in coldata.Keys)
3989 {
3990 thisHitColliders.Add(localid);
3991 if (!m_lastColliders.Contains(localid))
3992 {
3993 startedColliders.Add(localid);
3994 }
3995 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
3996 }
3997
3998 // calculate things that ended colliding
3999 foreach (uint localID in m_lastColliders)
4000 {
4001 if (!thisHitColliders.Contains(localID))
4002 {
4003 endedColliders.Add(localID);
4004 }
4005 }
4006 //add the items that started colliding this time to the last colliders list.
4007 foreach (uint localID in startedColliders)
4008 {
4009 m_lastColliders.Add(localID);
4010 }
4011 // remove things that ended colliding from the last colliders list
4012 foreach (uint localID in endedColliders)
4013 {
4014 m_lastColliders.Remove(localID);
4015 }
4016
4017 // do event notification
4018 if (startedColliders.Count > 0)
4019 {
4020 ColliderArgs StartCollidingMessage = new ColliderArgs();
4021 List<DetectedObject> colliding = new List<DetectedObject>();
4022 foreach (uint localId in startedColliders)
4023 {
4024 if (localId == 0)
4025 continue;
4026
4027 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4028 string data = "";
4029 if (obj != null)
4030 {
4031 DetectedObject detobj = new DetectedObject();
4032 detobj.keyUUID = obj.UUID;
4033 detobj.nameStr = obj.Name;
4034 detobj.ownerUUID = obj.OwnerID;
4035 detobj.posVector = obj.AbsolutePosition;
4036 detobj.rotQuat = obj.GetWorldRotation();
4037 detobj.velVector = obj.Velocity;
4038 detobj.colliderType = 0;
4039 detobj.groupUUID = obj.GroupID;
4040 colliding.Add(detobj);
4041 }
4042 }
4043
4044 if (colliding.Count > 0)
4045 {
4046 StartCollidingMessage.Colliders = colliding;
4047
4048 foreach (SceneObjectGroup att in GetAttachments())
4049 Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
4050 }
4051 }
4052
4053 if (endedColliders.Count > 0)
4054 {
4055 ColliderArgs EndCollidingMessage = new ColliderArgs();
4056 List<DetectedObject> colliding = new List<DetectedObject>();
4057 foreach (uint localId in endedColliders)
4058 {
4059 if (localId == 0)
4060 continue;
4061
4062 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4063 string data = "";
4064 if (obj != null)
4065 {
4066 DetectedObject detobj = new DetectedObject();
4067 detobj.keyUUID = obj.UUID;
4068 detobj.nameStr = obj.Name;
4069 detobj.ownerUUID = obj.OwnerID;
4070 detobj.posVector = obj.AbsolutePosition;
4071 detobj.rotQuat = obj.GetWorldRotation();
4072 detobj.velVector = obj.Velocity;
4073 detobj.colliderType = 0;
4074 detobj.groupUUID = obj.GroupID;
4075 colliding.Add(detobj);
4076 }
4077 }
4078
4079 if (colliding.Count > 0)
4080 {
4081 EndCollidingMessage.Colliders = colliding;
4082
4083 foreach (SceneObjectGroup att in GetAttachments())
4084 Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
4085 }
4086 }
4087
4088 if (thisHitColliders.Count > 0)
4089 {
4090 ColliderArgs CollidingMessage = new ColliderArgs();
4091 List<DetectedObject> colliding = new List<DetectedObject>();
4092 foreach (uint localId in thisHitColliders)
4093 {
4094 if (localId == 0)
4095 continue;
4096
4097 SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
4098 string data = "";
4099 if (obj != null)
4100 {
4101 DetectedObject detobj = new DetectedObject();
4102 detobj.keyUUID = obj.UUID;
4103 detobj.nameStr = obj.Name;
4104 detobj.ownerUUID = obj.OwnerID;
4105 detobj.posVector = obj.AbsolutePosition;
4106 detobj.rotQuat = obj.GetWorldRotation();
4107 detobj.velVector = obj.Velocity;
4108 detobj.colliderType = 0;
4109 detobj.groupUUID = obj.GroupID;
4110 colliding.Add(detobj);
4111 }
4112 }
4113
4114 if (colliding.Count > 0)
4115 {
4116 CollidingMessage.Colliders = colliding;
4117
4118 lock (m_attachments)
4119 {
4120 foreach (SceneObjectGroup att in m_attachments)
4121 Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
4122 }
4123 }
4124 }
4125 }
4126 finally
4127 {
4128 m_collisionEventFlag = false;
4129 }
4130 });
4131 }
4132
3862 private void TeleportFlagsDebug() { 4133 private void TeleportFlagsDebug() {
3863 4134
3864 // Some temporary debugging help to show all the TeleportFlags we have... 4135 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -3883,6 +4154,5 @@ namespace OpenSim.Region.Framework.Scenes
3883 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4154 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
3884 4155
3885 } 4156 }
3886
3887 } 4157 }
3888} 4158}
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;