aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes')
-rw-r--r--OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/CollisionSounds.cs377
-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.cs320
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs70
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs725
-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.cs479
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneManager.cs268
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs17
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs1350
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs1615
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs787
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs562
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs122
-rw-r--r--OpenSim/Region/Framework/Scenes/SimStatsReporter.cs97
-rw-r--r--OpenSim/Region/Framework/Scenes/UndoState.cs367
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs4
23 files changed, 6635 insertions, 1871 deletions
diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
index 14ae287..9ddac19 100644
--- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
+++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs
@@ -79,13 +79,13 @@ namespace OpenSim.Region.Framework.Scenes.Animation
79 m_scenePresence = sp; 79 m_scenePresence = sp;
80 CurrentMovementAnimation = "CROUCH"; 80 CurrentMovementAnimation = "CROUCH";
81 } 81 }
82 82
83 public void AddAnimation(UUID animID, UUID objectID) 83 public void AddAnimation(UUID animID, UUID objectID)
84 { 84 {
85 if (m_scenePresence.IsChildAgent) 85 if (m_scenePresence.IsChildAgent)
86 return; 86 return;
87 87
88// m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name); 88 // m_log.DebugFormat("[SCENE PRESENCE ANIMATOR]: Adding animation {0} for {1}", animID, m_scenePresence.Name);
89 89
90 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID)) 90 if (m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, objectID))
91 SendAnimPack(); 91 SendAnimPack();
@@ -117,6 +117,22 @@ namespace OpenSim.Region.Framework.Scenes.Animation
117 SendAnimPack(); 117 SendAnimPack();
118 } 118 }
119 119
120 public void avnChangeAnim(UUID animID, bool addRemove, bool sendPack)
121 {
122 if (m_scenePresence.IsChildAgent)
123 return;
124
125 if (animID != UUID.Zero)
126 {
127 if (addRemove)
128 m_animations.Add(animID, m_scenePresence.ControllingClient.NextAnimationSequenceNumber, UUID.Zero);
129 else
130 m_animations.Remove(animID);
131 }
132 if(sendPack)
133 SendAnimPack();
134 }
135
120 // Called from scripts 136 // Called from scripts
121 public void RemoveAnimation(string name) 137 public void RemoveAnimation(string name)
122 { 138 {
diff --git a/OpenSim/Region/Framework/Scenes/CollisionSounds.cs b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs
new file mode 100644
index 0000000..de82ddc
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs
@@ -0,0 +1,377 @@
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// Ubit 2012
28
29using System;
30using System.Collections.Generic;
31using OpenMetaverse;
32using OpenSim.Framework;
33
34namespace OpenSim.Region.Framework.Scenes
35{
36 public struct CollisionForSoundInfo
37 {
38 public uint colliderID;
39 public Vector3 position;
40 public float relativeVel;
41 }
42
43 public static class CollisionSounds
44 {
45 private const int MaxMaterials = 7;
46 // part part
47/*
48 private static UUID snd_StoneStone = new UUID("be7295c0-a158-11e1-b3dd-0800200c9a66");
49 private static UUID snd_StoneMetal = new UUID("be7295c0-a158-11e1-b3dd-0800201c9a66");
50 private static UUID snd_StoneGlass = new UUID("be7295c0-a158-11e1-b3dd-0800202c9a66");
51 private static UUID snd_StoneWood = new UUID("be7295c0-a158-11e1-b3dd-0800203c9a66");
52 private static UUID snd_StoneFlesh = new UUID("be7295c0-a158-11e1-b3dd-0800204c9a66");
53 private static UUID snd_StonePlastic = new UUID("be7295c0-a158-11e1-b3dd-0800205c9a66");
54 private static UUID snd_StoneRubber = new UUID("be7295c0-a158-11e1-b3dd-0800206c9a66");
55
56 private static UUID snd_MetalStone = new UUID("be7295c0-a158-11e1-b3dd-0801200c9a66");
57 private static UUID snd_MetalMetal = new UUID("be7295c0-a158-11e1-b3dd-0801201c9a66");
58 private static UUID snd_MetalGlass = new UUID("be7295c0-a158-11e1-b3dd-0801202c9a66");
59 private static UUID snd_MetalWood = new UUID("be7295c0-a158-11e1-b3dd-0801203c9a66");
60 private static UUID snd_MetalFlesh = new UUID("be7295c0-a158-11e1-b3dd-0801204c9a66");
61 private static UUID snd_MetalPlastic = new UUID("be7295c0-a158-11e1-b3dd-0801205c9a66");
62 private static UUID snd_MetalRubber = new UUID("be7295c0-a158-11e1-b3dd-0801206c9a66");
63
64 private static UUID snd_GlassStone = new UUID("be7295c0-a158-11e1-b3dd-0802200c9a66");
65 private static UUID snd_GlassMetal = new UUID("be7295c0-a158-11e1-b3dd-0802201c9a66");
66 private static UUID snd_GlassGlass = new UUID("be7295c0-a158-11e1-b3dd-0802202c9a66");
67 private static UUID snd_GlassWood = new UUID("be7295c0-a158-11e1-b3dd-0802203c9a66");
68 private static UUID snd_GlassFlesh = new UUID("be7295c0-a158-11e1-b3dd-0802204c9a66");
69 private static UUID snd_GlassPlastic = new UUID("be7295c0-a158-11e1-b3dd-0802205c9a66");
70 private static UUID snd_GlassRubber = new UUID("be7295c0-a158-11e1-b3dd-0802206c9a66");
71
72 private static UUID snd_WoodStone = new UUID("be7295c0-a158-11e1-b3dd-0803200c9a66");
73 private static UUID snd_WoodMetal = new UUID("be7295c0-a158-11e1-b3dd-0803201c9a66");
74 private static UUID snd_WoodGlass = new UUID("be7295c0-a158-11e1-b3dd-0803202c9a66");
75 private static UUID snd_WoodWood = new UUID("be7295c0-a158-11e1-b3dd-0803203c9a66");
76 private static UUID snd_WoodFlesh = new UUID("be7295c0-a158-11e1-b3dd-0803204c9a66");
77 private static UUID snd_WoodPlastic = new UUID("be7295c0-a158-11e1-b3dd-0803205c9a66");
78 private static UUID snd_WoodRubber = new UUID("be7295c0-a158-11e1-b3dd-0803206c9a66");
79
80 private static UUID snd_FleshStone = new UUID("be7295c0-a158-11e1-b3dd-0804200c9a66");
81 private static UUID snd_FleshMetal = new UUID("be7295c0-a158-11e1-b3dd-0804201c9a66");
82 private static UUID snd_FleshGlass = new UUID("be7295c0-a158-11e1-b3dd-0804202c9a66");
83 private static UUID snd_FleshWood = new UUID("be7295c0-a158-11e1-b3dd-0804203c9a66");
84 private static UUID snd_FleshFlesh = new UUID("be7295c0-a158-11e1-b3dd-0804204c9a66");
85 private static UUID snd_FleshPlastic = new UUID("be7295c0-a158-11e1-b3dd-0804205c9a66");
86 private static UUID snd_FleshRubber = new UUID("be7295c0-a158-11e1-b3dd-0804206c9a66");
87
88 private static UUID snd_PlasticStone = new UUID("be7295c0-a158-11e1-b3dd-0805200c9a66");
89 private static UUID snd_PlasticMetal = new UUID("be7295c0-a158-11e1-b3dd-0805201c9a66");
90 private static UUID snd_PlasticGlass = new UUID("be7295c0-a158-11e1-b3dd-0805202c9a66");
91 private static UUID snd_PlasticWood = new UUID("be7295c0-a158-11e1-b3dd-0805203c9a66");
92 private static UUID snd_PlasticFlesh = new UUID("be7295c0-a158-11e1-b3dd-0805204c9a66");
93 private static UUID snd_PlasticPlastic = new UUID("be7295c0-a158-11e1-b3dd-0805205c9a66");
94 private static UUID snd_PlasticRubber = new UUID("be7295c0-a158-11e1-b3dd-0805206c9a66");
95
96 private static UUID snd_RubberStone = new UUID("be7295c0-a158-11e1-b3dd-0806200c9a66");
97 private static UUID snd_RubberMetal = new UUID("be7295c0-a158-11e1-b3dd-0806201c9a66");
98 private static UUID snd_RubberGlass = new UUID("be7295c0-a158-11e1-b3dd-0806202c9a66");
99 private static UUID snd_RubberWood = new UUID("be7295c0-a158-11e1-b3dd-0806203c9a66");
100 private static UUID snd_RubberFlesh = new UUID("be7295c0-a158-11e1-b3dd-0806204c9a66");
101 private static UUID snd_RubberPlastic = new UUID("be7295c0-a158-11e1-b3dd-0806205c9a66");
102 private static UUID snd_RubberRubber = new UUID("be7295c0-a158-11e1-b3dd-0806206c9a66");
103
104 // terrain part
105 private static UUID snd_TerrainStone = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
106 private static UUID snd_TerrainMetal = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
107 private static UUID snd_TerrainGlass = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
108 private static UUID snd_TerrainWood = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
109 private static UUID snd_TerrainFlesh = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
110 private static UUID snd_TerrainPlastic = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
111 private static UUID snd_TerrainRubber = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
112*/
113 private static UUID snd_StoneStone = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
114 private static UUID snd_StoneMetal = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
115 private static UUID snd_StoneGlass = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
116 private static UUID snd_StoneWood = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
117 private static UUID snd_StoneFlesh = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
118 private static UUID snd_StonePlastic = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
119 private static UUID snd_StoneRubber = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
120
121 private static UUID snd_MetalMetal = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
122 private static UUID snd_MetalGlass = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
123 private static UUID snd_MetalWood = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
124 private static UUID snd_MetalFlesh = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
125 private static UUID snd_MetalPlastic = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
126 private static UUID snd_MetalRubber = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
127
128 private static UUID snd_GlassGlass = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
129 private static UUID snd_GlassWood = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
130 private static UUID snd_GlassFlesh = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
131 private static UUID snd_GlassPlastic = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
132 private static UUID snd_GlassRubber = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
133
134 private static UUID snd_WoodWood = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
135 private static UUID snd_WoodFlesh = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
136 private static UUID snd_WoodPlastic = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
137 private static UUID snd_WoodRubber = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
138
139 private static UUID snd_FleshFlesh = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
140 private static UUID snd_FleshPlastic = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
141 private static UUID snd_FleshRubber = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
142
143 private static UUID snd_PlasticPlastic = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
144 private static UUID snd_PlasticRubber = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
145
146 private static UUID snd_RubberRubber = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
147
148 // terrain part
149 private static UUID snd_TerrainStone = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
150 private static UUID snd_TerrainMetal = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
151 private static UUID snd_TerrainGlass = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
152 private static UUID snd_TerrainWood = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
153 private static UUID snd_TerrainFlesh = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
154 private static UUID snd_TerrainPlastic = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
155 private static UUID snd_TerrainRubber = new UUID("c80260ba-41fd-8a46-768a-6bf236360e3a");
156
157 public static UUID[] m_TerrainPart = {
158 snd_TerrainStone,
159 snd_TerrainMetal,
160 snd_TerrainGlass,
161 snd_TerrainWood,
162 snd_TerrainFlesh,
163 snd_TerrainPlastic,
164 snd_TerrainRubber
165 };
166/*
167 //full assimetric sounds
168 public static UUID[] m_PartPart = {
169 snd_StoneStone, snd_StoneMetal, snd_StoneGlass, snd_StoneWood, snd_StoneFlesh, snd_StonePlastic, snd_StoneRubber,
170 snd_MetalStone, snd_MetalMetal, snd_MetalGlass, snd_MetalWood, snd_MetalFlesh, snd_MetalPlastic, snd_MetalRubber,
171 snd_GlassStone, snd_GlassMetal, snd_GlassGlass, snd_GlassWood, snd_GlassFlesh, snd_GlassPlastic, snd_GlassRubber,
172 snd_WoodStone, snd_WoodMetal, snd_WoodGlass, snd_WoodWood, snd_WoodFlesh, snd_WoodPlastic, snd_WoodRubber,
173 snd_FleshStone, snd_FleshMetal, snd_FleshGlass, snd_FleshWood, snd_FleshFlesh, snd_FleshPlastic, snd_FleshRubber,
174 snd_PlasticStone, snd_PlasticMetal, snd_PlasticGlass, snd_PlasticWood, snd_PlasticFlesh, snd_PlasticPlastic, snd_PlasticRubber,
175 snd_RubberStone, snd_RubberMetal, snd_RubberGlass, snd_RubberWood, snd_RubberFlesh, snd_RubberPlastic, snd_RubberRubber
176 };
177*/
178 // simetric sounds
179 public static UUID[] m_PartPart = {
180 snd_StoneStone, snd_StoneMetal, snd_StoneGlass, snd_StoneWood, snd_StoneFlesh, snd_StonePlastic, snd_StoneRubber,
181 snd_StoneMetal, snd_MetalMetal, snd_MetalGlass, snd_MetalWood, snd_MetalFlesh, snd_MetalPlastic, snd_MetalRubber,
182 snd_StoneGlass, snd_MetalGlass, snd_GlassGlass, snd_GlassWood, snd_GlassFlesh, snd_GlassPlastic, snd_GlassRubber,
183 snd_StoneWood, snd_MetalWood, snd_GlassWood, snd_WoodWood, snd_WoodFlesh, snd_WoodPlastic, snd_WoodRubber,
184 snd_StoneFlesh, snd_MetalFlesh, snd_GlassFlesh, snd_WoodFlesh, snd_FleshFlesh, snd_FleshPlastic, snd_FleshRubber,
185 snd_StonePlastic, snd_MetalPlastic, snd_GlassPlastic, snd_WoodPlastic, snd_FleshPlastic, snd_PlasticPlastic, snd_PlasticRubber,
186 snd_StoneRubber, snd_MetalRubber, snd_GlassRubber, snd_WoodRubber, snd_FleshRubber, snd_PlasticRubber, snd_RubberRubber
187 };
188
189 public static void PartCollisionSound(SceneObjectPart part, List<CollisionForSoundInfo> collidersinfolist)
190 {
191 // disable for now
192 return;
193
194 if (collidersinfolist.Count == 0 || part == null)
195 return;
196
197 if (part.VolumeDetectActive || (part.Flags & PrimFlags.Physics) == 0)
198 return;
199
200 if (part.ParentGroup == null)
201 return;
202
203 if (part.CollisionSoundType < 0)
204 return;
205
206 float volume = 0.0f;
207 bool HaveSound = false;
208
209 UUID soundID = part.CollisionSound;
210
211 if (part.CollisionSoundType > 0)
212 {
213 // soundID = part.CollisionSound;
214 volume = part.CollisionSoundVolume;
215 if (volume == 0.0f)
216 return;
217 HaveSound = true;
218 }
219
220 bool doneownsound = false;
221
222 int thisMaterial = (int)part.Material;
223 if (thisMaterial >= MaxMaterials)
224 thisMaterial = 3;
225 int thisMatScaled = thisMaterial * MaxMaterials;
226
227 CollisionForSoundInfo colInfo;
228 uint id;
229
230 for(int i = 0; i< collidersinfolist.Count; i++)
231 {
232 colInfo = collidersinfolist[i];
233
234 id = colInfo.colliderID;
235 if (id == 0) // terrain collision
236 {
237 if (!doneownsound)
238 {
239 if (!HaveSound)
240 {
241 volume = Math.Abs(colInfo.relativeVel);
242 if (volume < 0.2f)
243 continue;
244
245 volume *= volume * .0625f; // 4m/s == full volume
246 if (volume > 1.0f)
247 volume = 1.0f;
248
249 soundID = m_TerrainPart[thisMaterial];
250 }
251 part.SendCollisionSound(soundID, volume, colInfo.position);
252 doneownsound = true;
253 }
254 continue;
255 }
256
257 SceneObjectPart otherPart = part.ParentGroup.Scene.GetSceneObjectPart(id);
258 if (otherPart != null)
259 {
260 if (otherPart.CollisionSoundType < 0 || otherPart.VolumeDetectActive)
261 continue;
262
263 if (!HaveSound)
264 {
265 if (otherPart.CollisionSoundType > 0)
266 {
267 soundID = otherPart.CollisionSound;
268 volume = otherPart.CollisionSoundVolume;
269 if (volume == 0.0f)
270 continue;
271 }
272 else
273 {
274 volume = Math.Abs(colInfo.relativeVel);
275 if (volume < 0.2f)
276 continue;
277
278 volume *= volume * .0625f; // 4m/s == full volume
279 if (volume > 1.0f)
280 volume = 1.0f;
281
282 int otherMaterial = (int)otherPart.Material;
283 if (otherMaterial >= MaxMaterials)
284 otherMaterial = 3;
285
286 soundID = m_PartPart[thisMatScaled + otherMaterial];
287 }
288 }
289
290 if (doneownsound)
291 otherPart.SendCollisionSound(soundID, volume, colInfo.position);
292 else
293 {
294 part.SendCollisionSound(soundID, volume, colInfo.position);
295 doneownsound = true;
296 }
297 }
298 }
299 }
300
301 public static void AvatarCollisionSound(ScenePresence av, List<CollisionForSoundInfo> collidersinfolist)
302 {
303 // disable for now
304 return;
305
306 if (collidersinfolist.Count == 0 || av == null)
307 return;
308
309 UUID soundID;
310 int otherMaterial;
311
312 int thisMaterial = 4; // flesh
313
314 int thisMatScaled = thisMaterial * MaxMaterials;
315
316 // bool doneownsound = false;
317
318 CollisionForSoundInfo colInfo;
319 uint id;
320 float volume;
321
322 for(int i = 0; i< collidersinfolist.Count; i++)
323 {
324 colInfo = collidersinfolist[i];
325
326 id = colInfo.colliderID;
327
328 if (id == 0) // no terrain collision sounds for now
329 {
330 continue;
331// volume = Math.Abs(colInfo.relativeVel);
332// if (volume < 0.2f)
333// continue;
334
335 }
336
337 SceneObjectPart otherPart = av.Scene.GetSceneObjectPart(id);
338 if (otherPart != null)
339 {
340 if (otherPart.CollisionSoundType < 0)
341 continue;
342 if (otherPart.CollisionSoundType > 0 && otherPart.CollisionSoundVolume > 0f)
343 otherPart.SendCollisionSound(otherPart.CollisionSound, otherPart.CollisionSoundVolume, colInfo.position);
344 else
345 {
346 volume = Math.Abs(colInfo.relativeVel);
347 if (volume < 0.2f)
348 continue;
349
350 volume *= volume * .0625f; // 4m/s == full volume
351 if (volume > 1.0f)
352 volume = 1.0f;
353 otherMaterial = (int)otherPart.Material;
354 if (otherMaterial >= MaxMaterials)
355 otherMaterial = 3;
356
357 soundID = m_PartPart[thisMatScaled + otherMaterial];
358 otherPart.SendCollisionSound(soundID, volume, colInfo.position);
359 }
360 continue;
361 }
362/*
363 else if (!doneownsound)
364 {
365 ScenePresence otherav = av.Scene.GetScenePresence(Id);
366 if (otherav != null && (!otherav.IsChildAgent))
367 {
368 soundID = snd_FleshFlesh;
369 av.SendCollisionSound(soundID, 1.0);
370 doneownsound = true;
371 }
372 }
373 */
374 }
375 }
376 }
377} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index f97b0a9..7688cf8 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -59,8 +59,12 @@ namespace OpenSim.Region.Framework.Scenes
59 59
60 public delegate void OnTerrainTickDelegate(); 60 public delegate void OnTerrainTickDelegate();
61 61
62 public delegate void OnTerrainUpdateDelegate();
63
62 public event OnTerrainTickDelegate OnTerrainTick; 64 public event OnTerrainTickDelegate OnTerrainTick;
63 65
66 public event OnTerrainUpdateDelegate OnTerrainUpdate;
67
64 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); 68 public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup);
65 69
66 public event OnBackupDelegate OnBackup; 70 public event OnBackupDelegate OnBackup;
@@ -896,6 +900,26 @@ namespace OpenSim.Region.Framework.Scenes
896 } 900 }
897 } 901 }
898 } 902 }
903 public void TriggerTerrainUpdate()
904 {
905 OnTerrainUpdateDelegate handlerTerrainUpdate = OnTerrainUpdate;
906 if (handlerTerrainUpdate != null)
907 {
908 foreach (OnTerrainUpdateDelegate d in handlerTerrainUpdate.GetInvocationList())
909 {
910 try
911 {
912 d();
913 }
914 catch (Exception e)
915 {
916 m_log.ErrorFormat(
917 "[EVENT MANAGER]: Delegate for TriggerTerrainUpdate failed - continuing. {0} {1}",
918 e.Message, e.StackTrace);
919 }
920 }
921 }
922 }
899 923
900 public void TriggerTerrainTick() 924 public void TriggerTerrainTick()
901 { 925 {
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 79c9309..270b01b 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -156,7 +156,7 @@ namespace OpenSim.Region.Framework.Scenes
156 return false; 156 return false;
157 } 157 }
158 } 158 }
159 159
160 if (InventoryService.AddItem(item)) 160 if (InventoryService.AddItem(item))
161 { 161 {
162 int userlevel = 0; 162 int userlevel = 0;
@@ -311,8 +311,7 @@ namespace OpenSim.Region.Framework.Scenes
311 311
312 // Update item with new asset 312 // Update item with new asset
313 item.AssetID = asset.FullID; 313 item.AssetID = asset.FullID;
314 if (group.UpdateInventoryItem(item)) 314 group.UpdateInventoryItem(item);
315 remoteClient.SendAgentAlertMessage("Script saved", false);
316 315
317 part.SendPropertiesToClient(remoteClient); 316 part.SendPropertiesToClient(remoteClient);
318 317
@@ -323,12 +322,7 @@ namespace OpenSim.Region.Framework.Scenes
323 { 322 {
324 // Needs to determine which engine was running it and use that 323 // Needs to determine which engine was running it and use that
325 // 324 //
326 part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); 325 errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0);
327 errors = part.Inventory.GetScriptErrors(item.ItemID);
328 }
329 else
330 {
331 remoteClient.SendAgentAlertMessage("Script saved", false);
332 } 326 }
333 327
334 // Tell anyone managing scripts that a script has been reloaded/changed 328 // Tell anyone managing scripts that a script has been reloaded/changed
@@ -396,6 +390,7 @@ namespace OpenSim.Region.Framework.Scenes
396 390
397 if (UUID.Zero == transactionID) 391 if (UUID.Zero == transactionID)
398 { 392 {
393 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
399 item.Name = itemUpd.Name; 394 item.Name = itemUpd.Name;
400 item.Description = itemUpd.Description; 395 item.Description = itemUpd.Description;
401 396
@@ -783,6 +778,8 @@ namespace OpenSim.Region.Framework.Scenes
783 return; 778 return;
784 } 779 }
785 780
781 if (newName == null) newName = item.Name;
782
786 AssetBase asset = AssetService.Get(item.AssetID.ToString()); 783 AssetBase asset = AssetService.Get(item.AssetID.ToString());
787 784
788 if (asset != null) 785 if (asset != null)
@@ -839,6 +836,24 @@ namespace OpenSim.Region.Framework.Scenes
839 } 836 }
840 837
841 /// <summary> 838 /// <summary>
839 /// Move an item within the agent's inventory, and leave a copy (used in making a new outfit)
840 /// </summary>
841 public void MoveInventoryItemsLeaveCopy(IClientAPI remoteClient, List<InventoryItemBase> items, UUID destfolder)
842 {
843 List<InventoryItemBase> moveitems = new List<InventoryItemBase>();
844 foreach (InventoryItemBase b in items)
845 {
846 CopyInventoryItem(remoteClient, 0, remoteClient.AgentId, b.ID, b.Folder, null);
847 InventoryItemBase n = InventoryService.GetItem(b);
848 n.Folder = destfolder;
849 moveitems.Add(n);
850 remoteClient.SendInventoryItemCreateUpdate(n, 0);
851 }
852
853 MoveInventoryItem(remoteClient, moveitems);
854 }
855
856 /// <summary>
842 /// Move an item within the agent's inventory. 857 /// Move an item within the agent's inventory.
843 /// </summary> 858 /// </summary>
844 /// <param name="remoteClient"></param> 859 /// <param name="remoteClient"></param>
@@ -1181,6 +1196,10 @@ namespace OpenSim.Region.Framework.Scenes
1181 { 1196 {
1182 SceneObjectPart part = GetSceneObjectPart(primLocalId); 1197 SceneObjectPart part = GetSceneObjectPart(primLocalId);
1183 1198
1199 // Can't move a null item
1200 if (itemId == UUID.Zero)
1201 return;
1202
1184 if (null == part) 1203 if (null == part)
1185 { 1204 {
1186 m_log.WarnFormat( 1205 m_log.WarnFormat(
@@ -1285,21 +1304,28 @@ namespace OpenSim.Region.Framework.Scenes
1285 return; 1304 return;
1286 } 1305 }
1287 1306
1288 if (part.OwnerID != destPart.OwnerID) 1307 // Can't transfer this
1308 //
1309 if (part.OwnerID != destPart.OwnerID && (srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1310 return;
1311
1312 bool overrideNoMod = false;
1313 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0)
1314 overrideNoMod = true;
1315
1316 if (part.OwnerID != destPart.OwnerID && (destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1289 { 1317 {
1290 // Source must have transfer permissions 1318 // object cannot copy items to an object owned by a different owner
1291 if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) 1319 // unless llAllowInventoryDrop has been called
1292 return;
1293 1320
1294 // Object cannot copy items to an object owned by a different owner 1321 return;
1295 // unless llAllowInventoryDrop has been called on the destination
1296 if ((destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0)
1297 return;
1298 } 1322 }
1299 1323
1300 // must have both move and modify permission to put an item in an object 1324 // must have both move and modify permission to put an item in an object
1301 if ((part.OwnerMask & ((uint)PermissionMask.Move | (uint)PermissionMask.Modify)) == 0) 1325 if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod))
1326 {
1302 return; 1327 return;
1328 }
1303 1329
1304 TaskInventoryItem destTaskItem = new TaskInventoryItem(); 1330 TaskInventoryItem destTaskItem = new TaskInventoryItem();
1305 1331
@@ -1355,6 +1381,14 @@ namespace OpenSim.Region.Framework.Scenes
1355 1381
1356 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items) 1382 public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List<UUID> items)
1357 { 1383 {
1384 SceneObjectPart destPart = GetSceneObjectPart(destID);
1385 if (destPart != null) // Move into a prim
1386 {
1387 foreach(UUID itemID in items)
1388 MoveTaskInventoryItem(destID, host, itemID);
1389 return destID; // Prim folder ID == prim ID
1390 }
1391
1358 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); 1392 InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID);
1359 1393
1360 UUID newFolderID = UUID.Random(); 1394 UUID newFolderID = UUID.Random();
@@ -1540,12 +1574,12 @@ namespace OpenSim.Region.Framework.Scenes
1540 agentTransactions.HandleTaskItemUpdateFromTransaction( 1574 agentTransactions.HandleTaskItemUpdateFromTransaction(
1541 remoteClient, part, transactionID, currentItem); 1575 remoteClient, part, transactionID, currentItem);
1542 1576
1543 if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) 1577// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard)
1544 remoteClient.SendAgentAlertMessage("Notecard saved", false); 1578// remoteClient.SendAgentAlertMessage("Notecard saved", false);
1545 else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) 1579// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL)
1546 remoteClient.SendAgentAlertMessage("Script saved", false); 1580// remoteClient.SendAgentAlertMessage("Script saved", false);
1547 else 1581// else
1548 remoteClient.SendAgentAlertMessage("Item saved", false); 1582// remoteClient.SendAgentAlertMessage("Item saved", false);
1549 } 1583 }
1550 } 1584 }
1551 1585
@@ -1729,7 +1763,7 @@ namespace OpenSim.Region.Framework.Scenes
1729 } 1763 }
1730 1764
1731 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, 1765 AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType,
1732 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), 1766 Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n\n touch_start(integer num)\n {\n }\n}"),
1733 agentID); 1767 agentID);
1734 AssetService.Store(asset); 1768 AssetService.Store(asset);
1735 1769
@@ -1885,23 +1919,32 @@ namespace OpenSim.Region.Framework.Scenes
1885 // build a list of eligible objects 1919 // build a list of eligible objects
1886 List<uint> deleteIDs = new List<uint>(); 1920 List<uint> deleteIDs = new List<uint>();
1887 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>(); 1921 List<SceneObjectGroup> deleteGroups = new List<SceneObjectGroup>();
1888 1922 List<SceneObjectGroup> takeGroups = new List<SceneObjectGroup>();
1889 // Start with true for both, then remove the flags if objects
1890 // that we can't derez are part of the selection
1891 bool permissionToTake = true;
1892 bool permissionToTakeCopy = true;
1893 bool permissionToDelete = true;
1894 1923
1895 foreach (uint localID in localIDs) 1924 foreach (uint localID in localIDs)
1896 { 1925 {
1926 // Start with true for both, then remove the flags if objects
1927 // that we can't derez are part of the selection
1928 bool permissionToTake = true;
1929 bool permissionToTakeCopy = true;
1930 bool permissionToDelete = true;
1931
1897 // Invalid id 1932 // Invalid id
1898 SceneObjectPart part = GetSceneObjectPart(localID); 1933 SceneObjectPart part = GetSceneObjectPart(localID);
1899 if (part == null) 1934 if (part == null)
1935 {
1936 //Client still thinks the object exists, kill it
1937 deleteIDs.Add(localID);
1900 continue; 1938 continue;
1939 }
1901 1940
1902 // Already deleted by someone else 1941 // Already deleted by someone else
1903 if (part.ParentGroup.IsDeleted) 1942 if (part.ParentGroup.IsDeleted)
1943 {
1944 //Client still thinks the object exists, kill it
1945 deleteIDs.Add(localID);
1904 continue; 1946 continue;
1947 }
1905 1948
1906 // Can't delete child prims 1949 // Can't delete child prims
1907 if (part != part.ParentGroup.RootPart) 1950 if (part != part.ParentGroup.RootPart)
@@ -1909,9 +1952,6 @@ namespace OpenSim.Region.Framework.Scenes
1909 1952
1910 SceneObjectGroup grp = part.ParentGroup; 1953 SceneObjectGroup grp = part.ParentGroup;
1911 1954
1912 deleteIDs.Add(localID);
1913 deleteGroups.Add(grp);
1914
1915 if (remoteClient == null) 1955 if (remoteClient == null)
1916 { 1956 {
1917 // Autoreturn has a null client. Nothing else does. So 1957 // Autoreturn has a null client. Nothing else does. So
@@ -1928,83 +1968,195 @@ namespace OpenSim.Region.Framework.Scenes
1928 } 1968 }
1929 else 1969 else
1930 { 1970 {
1931 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) 1971 if (action == DeRezAction.TakeCopy)
1972 {
1973 if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId))
1974 permissionToTakeCopy = false;
1975 }
1976 else
1977 {
1932 permissionToTakeCopy = false; 1978 permissionToTakeCopy = false;
1933 1979 }
1934 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) 1980 if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId))
1935 permissionToTake = false; 1981 permissionToTake = false;
1936 1982
1937 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) 1983 if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId))
1938 permissionToDelete = false; 1984 permissionToDelete = false;
1939 } 1985 }
1940 }
1941 1986
1942 // Handle god perms 1987 // Handle god perms
1943 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) 1988 if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId))
1944 { 1989 {
1945 permissionToTake = true; 1990 permissionToTake = true;
1946 permissionToTakeCopy = true; 1991 permissionToTakeCopy = true;
1947 permissionToDelete = true; 1992 permissionToDelete = true;
1948 } 1993 }
1949 1994
1950 // If we're re-saving, we don't even want to delete 1995 // If we're re-saving, we don't even want to delete
1951 if (action == DeRezAction.SaveToExistingUserInventoryItem) 1996 if (action == DeRezAction.SaveToExistingUserInventoryItem)
1952 permissionToDelete = false; 1997 permissionToDelete = false;
1953 1998
1954 // if we want to take a copy, we also don't want to delete 1999 // if we want to take a copy, we also don't want to delete
1955 // Note: after this point, the permissionToTakeCopy flag 2000 // Note: after this point, the permissionToTakeCopy flag
1956 // becomes irrelevant. It already includes the permissionToTake 2001 // becomes irrelevant. It already includes the permissionToTake
1957 // permission and after excluding no copy items here, we can 2002 // permission and after excluding no copy items here, we can
1958 // just use that. 2003 // just use that.
1959 if (action == DeRezAction.TakeCopy) 2004 if (action == DeRezAction.TakeCopy)
1960 { 2005 {
1961 // If we don't have permission, stop right here 2006 // If we don't have permission, stop right here
1962 if (!permissionToTakeCopy) 2007 if (!permissionToTakeCopy)
1963 return; 2008 return;
1964 2009
1965 permissionToTake = true; 2010 permissionToTake = true;
1966 // Don't delete 2011 // Don't delete
1967 permissionToDelete = false; 2012 permissionToDelete = false;
1968 } 2013 }
1969 2014
1970 if (action == DeRezAction.Return) 2015 if (action == DeRezAction.Return)
1971 {
1972 if (remoteClient != null)
1973 { 2016 {
1974 if (Permissions.CanReturnObjects( 2017 if (remoteClient != null)
1975 null,
1976 remoteClient.AgentId,
1977 deleteGroups))
1978 { 2018 {
1979 permissionToTake = true; 2019 if (Permissions.CanReturnObjects(
1980 permissionToDelete = true; 2020 null,
1981 2021 remoteClient.AgentId,
1982 foreach (SceneObjectGroup g in deleteGroups) 2022 deleteGroups))
1983 { 2023 {
1984 AddReturn(g.OwnerID == g.GroupID ? g.LastOwnerID : g.OwnerID, g.Name, g.AbsolutePosition, "parcel owner return"); 2024 permissionToTake = true;
2025 permissionToDelete = true;
2026
2027 AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return");
1985 } 2028 }
1986 } 2029 }
2030 else // Auto return passes through here with null agent
2031 {
2032 permissionToTake = true;
2033 permissionToDelete = true;
2034 }
1987 } 2035 }
1988 else // Auto return passes through here with null agent 2036
2037 if (permissionToTake && (!permissionToDelete))
2038 takeGroups.Add(grp);
2039
2040 if (permissionToDelete)
1989 { 2041 {
1990 permissionToTake = true; 2042 if (permissionToTake)
1991 permissionToDelete = true; 2043 deleteGroups.Add(grp);
2044 deleteIDs.Add(grp.LocalId);
1992 } 2045 }
1993 } 2046 }
1994 2047
1995 if (permissionToTake && (action != DeRezAction.Delete || this.m_useTrashOnDelete)) 2048 SendKillObject(deleteIDs);
2049
2050 if (deleteGroups.Count > 0)
1996 { 2051 {
2052 foreach (SceneObjectGroup g in deleteGroups)
2053 deleteIDs.Remove(g.LocalId);
2054
1997 m_asyncSceneObjectDeleter.DeleteToInventory( 2055 m_asyncSceneObjectDeleter.DeleteToInventory(
1998 action, destinationID, deleteGroups, remoteClient, 2056 action, destinationID, deleteGroups, remoteClient,
1999 permissionToDelete); 2057 true);
2000 } 2058 }
2001 else if (permissionToDelete) 2059 if (takeGroups.Count > 0)
2060 {
2061 m_asyncSceneObjectDeleter.DeleteToInventory(
2062 action, destinationID, takeGroups, remoteClient,
2063 false);
2064 }
2065 if (deleteIDs.Count > 0)
2002 { 2066 {
2003 foreach (SceneObjectGroup g in deleteGroups) 2067 foreach (SceneObjectGroup g in deleteGroups)
2004 DeleteSceneObject(g, false); 2068 DeleteSceneObject(g, true);
2005 } 2069 }
2006 } 2070 }
2007 2071
2072 public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
2073 {
2074 itemID = UUID.Zero;
2075 if (grp != null)
2076 {
2077 Vector3 inventoryStoredPosition = new Vector3
2078 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
2079 ? 250
2080 : grp.AbsolutePosition.X)
2081 ,
2082 (grp.AbsolutePosition.X > (int)Constants.RegionSize)
2083 ? 250
2084 : grp.AbsolutePosition.X,
2085 grp.AbsolutePosition.Z);
2086
2087 Vector3 originalPosition = grp.AbsolutePosition;
2088
2089 grp.AbsolutePosition = inventoryStoredPosition;
2090
2091 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
2092
2093 grp.AbsolutePosition = originalPosition;
2094
2095 AssetBase asset = CreateAsset(
2096 grp.GetPartName(grp.LocalId),
2097 grp.GetPartDescription(grp.LocalId),
2098 (sbyte)AssetType.Object,
2099 Utils.StringToBytes(sceneObjectXml),
2100 remoteClient.AgentId);
2101 AssetService.Store(asset);
2102
2103 InventoryItemBase item = new InventoryItemBase();
2104 item.CreatorId = grp.RootPart.CreatorID.ToString();
2105 item.CreatorData = grp.RootPart.CreatorData;
2106 item.Owner = remoteClient.AgentId;
2107 item.ID = UUID.Random();
2108 item.AssetID = asset.FullID;
2109 item.Description = asset.Description;
2110 item.Name = asset.Name;
2111 item.AssetType = asset.Type;
2112 item.InvType = (int)InventoryType.Object;
2113
2114 InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object);
2115 if (folder != null)
2116 item.Folder = folder.ID;
2117 else // oopsies
2118 item.Folder = UUID.Zero;
2119
2120 // Set up base perms properly
2121 uint permsBase = (uint)(PermissionMask.Move | PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify);
2122 permsBase &= grp.RootPart.BaseMask;
2123 permsBase |= (uint)PermissionMask.Move;
2124
2125 // Make sure we don't lock it
2126 grp.RootPart.NextOwnerMask |= (uint)PermissionMask.Move;
2127
2128 if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions())
2129 {
2130 item.BasePermissions = permsBase & grp.RootPart.NextOwnerMask;
2131 item.CurrentPermissions = permsBase & grp.RootPart.NextOwnerMask;
2132 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2133 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask & grp.RootPart.NextOwnerMask;
2134 item.GroupPermissions = permsBase & grp.RootPart.GroupMask & grp.RootPart.NextOwnerMask;
2135 }
2136 else
2137 {
2138 item.BasePermissions = permsBase;
2139 item.CurrentPermissions = permsBase & grp.RootPart.OwnerMask;
2140 item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask;
2141 item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask;
2142 item.GroupPermissions = permsBase & grp.RootPart.GroupMask;
2143 }
2144 item.CreationDate = Util.UnixTimeSinceEpoch();
2145
2146 // sets itemID so client can show item as 'attached' in inventory
2147 grp.FromItemID = item.ID;
2148
2149 if (AddInventoryItem(item))
2150 remoteClient.SendInventoryItemCreateUpdate(item, 0);
2151 else
2152 m_dialogModule.SendAlertToUser(remoteClient, "Operation failed");
2153
2154 itemID = item.ID;
2155 return item.AssetID;
2156 }
2157 return UUID.Zero;
2158 }
2159
2008 /// <summary> 2160 /// <summary>
2009 /// Event Handler Rez an object into a scene 2161 /// Event Handler Rez an object into a scene
2010 /// Calls the non-void event handler 2162 /// Calls the non-void event handler
@@ -2131,6 +2283,9 @@ namespace OpenSim.Region.Framework.Scenes
2131 2283
2132 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running) 2284 public void SetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID, bool running)
2133 { 2285 {
2286 if (!Permissions.CanEditScript(itemID, objectID, controllingClient.AgentId))
2287 return;
2288
2134 SceneObjectPart part = GetSceneObjectPart(objectID); 2289 SceneObjectPart part = GetSceneObjectPart(objectID);
2135 if (part == null) 2290 if (part == null)
2136 return; 2291 return;
@@ -2187,7 +2342,10 @@ namespace OpenSim.Region.Framework.Scenes
2187 } 2342 }
2188 else 2343 else
2189 { 2344 {
2190 if (!Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)) 2345 if (!Permissions.IsGod(remoteClient.AgentId) && sog.OwnerID != remoteClient.AgentId)
2346 continue;
2347
2348 if (!Permissions.CanTransferObject(sog.UUID, groupID))
2191 continue; 2349 continue;
2192 2350
2193 if (sog.GroupID != groupID) 2351 if (sog.GroupID != groupID)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
index 2701d6e..cf68ff4 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs
@@ -149,27 +149,47 @@ namespace OpenSim.Region.Framework.Scenes
149 /// <param name="remoteClient"></param> 149 /// <param name="remoteClient"></param>
150 public void SelectPrim(uint primLocalID, IClientAPI remoteClient) 150 public void SelectPrim(uint primLocalID, IClientAPI remoteClient)
151 { 151 {
152 /*
153 SceneObjectPart part = GetSceneObjectPart(primLocalID);
154
155 if (null == part)
156 return;
157
158 if (part.IsRoot)
159 {
160 SceneObjectGroup sog = part.ParentGroup;
161 sog.SendPropertiesToClient(remoteClient);
162
163 // A prim is only tainted if it's allowed to be edited by the person clicking it.
164 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
165 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
166 {
167 sog.IsSelected = true;
168 EventManager.TriggerParcelPrimCountTainted();
169 }
170 }
171 else
172 {
173 part.SendPropertiesToClient(remoteClient);
174 }
175 */
152 SceneObjectPart part = GetSceneObjectPart(primLocalID); 176 SceneObjectPart part = GetSceneObjectPart(primLocalID);
153 177
154 if (null == part) 178 if (null == part)
155 return; 179 return;
156 180
157 if (part.IsRoot) 181 SceneObjectGroup sog = part.ParentGroup;
158 { 182 if (sog == null)
159 SceneObjectGroup sog = part.ParentGroup; 183 return;
160 sog.SendPropertiesToClient(remoteClient);
161 sog.IsSelected = true;
162 184
163 // A prim is only tainted if it's allowed to be edited by the person clicking it. 185 part.SendPropertiesToClient(remoteClient);
164 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) 186
165 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) 187 // A prim is only tainted if it's allowed to be edited by the person clicking it.
166 { 188 if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId)
167 EventManager.TriggerParcelPrimCountTainted(); 189 || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId))
168 }
169 }
170 else
171 { 190 {
172 part.SendPropertiesToClient(remoteClient); 191 part.IsSelected = true;
192 EventManager.TriggerParcelPrimCountTainted();
173 } 193 }
174 } 194 }
175 195
@@ -222,7 +242,7 @@ namespace OpenSim.Region.Framework.Scenes
222 SceneObjectPart part = GetSceneObjectPart(primLocalID); 242 SceneObjectPart part = GetSceneObjectPart(primLocalID);
223 if (part == null) 243 if (part == null)
224 return; 244 return;
225 245 /*
226 // A deselect packet contains all the local prims being deselected. However, since selection is still 246 // A deselect packet contains all the local prims being deselected. However, since selection is still
227 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims 247 // group based we only want the root prim to trigger a full update - otherwise on objects with many prims
228 // we end up sending many duplicate ObjectUpdates 248 // we end up sending many duplicate ObjectUpdates
@@ -235,7 +255,9 @@ namespace OpenSim.Region.Framework.Scenes
235 // handled by group, but by prim. Legacy cruft. 255 // handled by group, but by prim. Legacy cruft.
236 // TODO: Make selection flagging per prim! 256 // TODO: Make selection flagging per prim!
237 // 257 //
238 part.ParentGroup.IsSelected = false; 258 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
259 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
260 part.ParentGroup.IsSelected = false;
239 261
240 if (part.ParentGroup.IsAttachment) 262 if (part.ParentGroup.IsAttachment)
241 isAttachment = true; 263 isAttachment = true;
@@ -255,6 +277,22 @@ namespace OpenSim.Region.Framework.Scenes
255 part.UUID, remoteClient.AgentId)) 277 part.UUID, remoteClient.AgentId))
256 EventManager.TriggerParcelPrimCountTainted(); 278 EventManager.TriggerParcelPrimCountTainted();
257 } 279 }
280 */
281
282 bool oldgprSelect = part.ParentGroup.IsSelected;
283
284 // This is wrong, wrong, wrong. Selection should not be
285 // handled by group, but by prim. Legacy cruft.
286 // TODO: Make selection flagging per prim!
287 //
288 if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)
289 || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId))
290 {
291 part.IsSelected = false;
292 if (!part.ParentGroup.IsAttachment && oldgprSelect != part.ParentGroup.IsSelected)
293 EventManager.TriggerParcelPrimCountTainted();
294 }
295
258 } 296 }
259 297
260 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount, 298 public virtual void ProcessMoneyTransferRequest(UUID source, UUID destination, int amount,
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 702e322..b79892d 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -124,6 +124,7 @@ namespace OpenSim.Region.Framework.Scenes
124 // TODO: need to figure out how allow client agents but deny 124 // TODO: need to figure out how allow client agents but deny
125 // root agents when ACL denies access to root agent 125 // root agents when ACL denies access to root agent
126 public bool m_strictAccessControl = true; 126 public bool m_strictAccessControl = true;
127 public bool m_seeIntoBannedRegion = false;
127 public int MaxUndoCount = 5; 128 public int MaxUndoCount = 5;
128 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet; 129 // Using this for RegionReady module to prevent LoginsDisabled from changing under our feet;
129 public bool LoginLock = false; 130 public bool LoginLock = false;
@@ -139,12 +140,14 @@ namespace OpenSim.Region.Framework.Scenes
139 140
140 protected int m_splitRegionID; 141 protected int m_splitRegionID;
141 protected Timer m_restartWaitTimer = new Timer(); 142 protected Timer m_restartWaitTimer = new Timer();
143 protected Timer m_timerWatchdog = new Timer();
142 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>(); 144 protected List<RegionInfo> m_regionRestartNotifyList = new List<RegionInfo>();
143 protected List<RegionInfo> m_neighbours = new List<RegionInfo>(); 145 protected List<RegionInfo> m_neighbours = new List<RegionInfo>();
144 protected string m_simulatorVersion = "OpenSimulator Server"; 146 protected string m_simulatorVersion = "OpenSimulator Server";
145 protected ModuleLoader m_moduleLoader; 147 protected ModuleLoader m_moduleLoader;
146 protected AgentCircuitManager m_authenticateHandler; 148 protected AgentCircuitManager m_authenticateHandler;
147 protected SceneCommunicationService m_sceneGridService; 149 protected SceneCommunicationService m_sceneGridService;
150 protected ISnmpModule m_snmpService = null;
148 151
149 protected ISimulationDataService m_SimulationDataService; 152 protected ISimulationDataService m_SimulationDataService;
150 protected IEstateDataService m_EstateDataService; 153 protected IEstateDataService m_EstateDataService;
@@ -206,7 +209,7 @@ namespace OpenSim.Region.Framework.Scenes
206 private int m_update_events = 1; 209 private int m_update_events = 1;
207 private int m_update_backup = 200; 210 private int m_update_backup = 200;
208 private int m_update_terrain = 50; 211 private int m_update_terrain = 50;
209// private int m_update_land = 1; 212 private int m_update_land = 10;
210 private int m_update_coarse_locations = 50; 213 private int m_update_coarse_locations = 50;
211 214
212 private int agentMS; 215 private int agentMS;
@@ -225,6 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
225 /// </summary> 228 /// </summary>
226 private int m_lastFrameTick; 229 private int m_lastFrameTick;
227 230
231 public bool CombineRegions = false;
228 /// <summary> 232 /// <summary>
229 /// Tick at which the last maintenance run occurred. 233 /// Tick at which the last maintenance run occurred.
230 /// </summary> 234 /// </summary>
@@ -255,6 +259,11 @@ namespace OpenSim.Region.Framework.Scenes
255 /// </summary> 259 /// </summary>
256 private int m_LastLogin; 260 private int m_LastLogin;
257 261
262 private int m_lastIncoming;
263 private int m_lastOutgoing;
264 private int m_hbRestarts = 0;
265
266
258 /// <summary> 267 /// <summary>
259 /// Thread that runs the scene loop. 268 /// Thread that runs the scene loop.
260 /// </summary> 269 /// </summary>
@@ -270,7 +279,7 @@ namespace OpenSim.Region.Framework.Scenes
270 private volatile bool m_shuttingDown; 279 private volatile bool m_shuttingDown;
271 280
272// private int m_lastUpdate; 281// private int m_lastUpdate;
273// private bool m_firstHeartbeat = true; 282 private bool m_firstHeartbeat = true;
274 283
275 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; 284 private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time;
276 private bool m_reprioritizationEnabled = true; 285 private bool m_reprioritizationEnabled = true;
@@ -315,6 +324,19 @@ namespace OpenSim.Region.Framework.Scenes
315 get { return m_sceneGridService; } 324 get { return m_sceneGridService; }
316 } 325 }
317 326
327 public ISnmpModule SnmpService
328 {
329 get
330 {
331 if (m_snmpService == null)
332 {
333 m_snmpService = RequestModuleInterface<ISnmpModule>();
334 }
335
336 return m_snmpService;
337 }
338 }
339
318 public ISimulationDataService SimulationDataService 340 public ISimulationDataService SimulationDataService
319 { 341 {
320 get 342 get
@@ -613,6 +635,8 @@ namespace OpenSim.Region.Framework.Scenes
613 m_EstateDataService = estateDataService; 635 m_EstateDataService = estateDataService;
614 m_regionHandle = m_regInfo.RegionHandle; 636 m_regionHandle = m_regInfo.RegionHandle;
615 m_regionName = m_regInfo.RegionName; 637 m_regionName = m_regInfo.RegionName;
638 m_lastIncoming = 0;
639 m_lastOutgoing = 0;
616 640
617 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this); 641 m_asyncSceneObjectDeleter = new AsyncSceneObjectGroupDeleter(this);
618 m_asyncSceneObjectDeleter.Enabled = true; 642 m_asyncSceneObjectDeleter.Enabled = true;
@@ -693,102 +717,111 @@ namespace OpenSim.Region.Framework.Scenes
693 717
694 // Region config overrides global config 718 // Region config overrides global config
695 // 719 //
696 if (m_config.Configs["Startup"] != null) 720 try
697 { 721 {
698 IConfig startupConfig = m_config.Configs["Startup"]; 722 if (m_config.Configs["Startup"] != null)
699
700 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance", m_defaultDrawDistance);
701 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
702 if (!m_useBackup)
703 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
704
705 //Animation states
706 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
707
708 PhysicalPrims = startupConfig.GetBoolean("physical_prim", PhysicalPrims);
709 CollidablePrims = startupConfig.GetBoolean("collidable_prim", CollidablePrims);
710
711 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
712 if (RegionInfo.NonphysPrimMax > 0)
713 { 723 {
714 m_maxNonphys = RegionInfo.NonphysPrimMax; 724 IConfig startupConfig = m_config.Configs["Startup"];
715 }
716
717 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
718 725
719 if (RegionInfo.PhysPrimMax > 0) 726 m_defaultDrawDistance = startupConfig.GetFloat("DefaultDrawDistance",m_defaultDrawDistance);
720 { 727 m_useBackup = startupConfig.GetBoolean("UseSceneBackup", m_useBackup);
721 m_maxPhys = RegionInfo.PhysPrimMax; 728 if (!m_useBackup)
722 } 729 m_log.InfoFormat("[SCENE]: Backup has been disabled for {0}", RegionInfo.RegionName);
730
731 //Animation states
732 m_useFlySlow = startupConfig.GetBoolean("enableflyslow", false);
723 733
724 // Here, if clamping is requested in either global or 734 PhysicalPrims = startupConfig.GetBoolean("physical_prim", true);
725 // local config, it will be used 735 CollidablePrims = startupConfig.GetBoolean("collidable_prim", true);
726 //
727 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
728 if (RegionInfo.ClampPrimSize)
729 {
730 m_clampPrimSize = true;
731 }
732 736
733 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete", m_useTrashOnDelete); 737 m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys);
734 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries); 738 if (RegionInfo.NonphysPrimMax > 0)
735 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings); 739 {
736 m_dontPersistBefore = 740 m_maxNonphys = RegionInfo.NonphysPrimMax;
737 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE); 741 }
738 m_dontPersistBefore *= 10000000;
739 m_persistAfter =
740 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
741 m_persistAfter *= 10000000;
742 742
743 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); 743 m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys);
744 744
745 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); 745 if (RegionInfo.PhysPrimMax > 0)
746 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); 746 {
747 m_maxPhys = RegionInfo.PhysPrimMax;
748 }
747 749
748 IConfig packetConfig = m_config.Configs["PacketPool"]; 750 SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest");
749 if (packetConfig != null) 751 TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false);
750 {
751 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
752 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
753 }
754 752
755 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 753 // Here, if clamping is requested in either global or
754 // local config, it will be used
755 //
756 m_clampPrimSize = startupConfig.GetBoolean("ClampPrimSize", m_clampPrimSize);
757 if (RegionInfo.ClampPrimSize)
758 {
759 m_clampPrimSize = true;
760 }
756 761
757 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true); 762 m_useTrashOnDelete = startupConfig.GetBoolean("UseTrashOnDelete",m_useTrashOnDelete);
758 if (m_generateMaptiles) 763 m_trustBinaries = startupConfig.GetBoolean("TrustBinaries", m_trustBinaries);
759 { 764 m_allowScriptCrossings = startupConfig.GetBoolean("AllowScriptCrossing", m_allowScriptCrossings);
760 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0); 765 m_dontPersistBefore =
761 if (maptileRefresh != 0) 766 startupConfig.GetLong("MinimumTimeBeforePersistenceConsidered", DEFAULT_MIN_TIME_FOR_PERSISTENCE);
767 m_dontPersistBefore *= 10000000;
768 m_persistAfter =
769 startupConfig.GetLong("MaximumTimeBeforePersistenceConsidered", DEFAULT_MAX_TIME_FOR_PERSISTENCE);
770 m_persistAfter *= 10000000;
771
772 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine");
773 m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine);
774
775 IConfig packetConfig = m_config.Configs["PacketPool"];
776 if (packetConfig != null)
762 { 777 {
763 m_mapGenerationTimer.Interval = maptileRefresh * 1000; 778 PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true);
764 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister; 779 PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true);
765 m_mapGenerationTimer.AutoReset = true;
766 m_mapGenerationTimer.Start();
767 } 780 }
768 }
769 else
770 {
771 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
772 UUID tileID;
773 781
774 if (UUID.TryParse(tile, out tileID)) 782 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
783 m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion);
784 CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false);
785
786 m_generateMaptiles = startupConfig.GetBoolean("GenerateMaptiles", true);
787 if (m_generateMaptiles)
775 { 788 {
776 RegionInfo.RegionSettings.TerrainImageID = tileID; 789 int maptileRefresh = startupConfig.GetInt("MaptileRefresh", 0);
790 if (maptileRefresh != 0)
791 {
792 m_mapGenerationTimer.Interval = maptileRefresh * 1000;
793 m_mapGenerationTimer.Elapsed += RegenerateMaptileAndReregister;
794 m_mapGenerationTimer.AutoReset = true;
795 m_mapGenerationTimer.Start();
796 }
777 } 797 }
778 } 798 else
799 {
800 string tile = startupConfig.GetString("MaptileStaticUUID", UUID.Zero.ToString());
801 UUID tileID;
779 802
780 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime); 803 if (UUID.TryParse(tile, out tileID))
781 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup); 804 {
782 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations); 805 RegionInfo.RegionSettings.TerrainImageID = tileID;
783 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement); 806 }
784 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events); 807 }
785 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
786 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
787 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
788 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
789 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
790 808
791 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates); 809 MinFrameTime = startupConfig.GetFloat( "MinFrameTime", MinFrameTime);
810 m_update_backup = startupConfig.GetInt( "UpdateStorageEveryNFrames", m_update_backup);
811 m_update_coarse_locations = startupConfig.GetInt( "UpdateCoarseLocationsEveryNFrames", m_update_coarse_locations);
812 m_update_entitymovement = startupConfig.GetInt( "UpdateEntityMovementEveryNFrames", m_update_entitymovement);
813 m_update_events = startupConfig.GetInt( "UpdateEventsEveryNFrames", m_update_events);
814 m_update_objects = startupConfig.GetInt( "UpdateObjectsEveryNFrames", m_update_objects);
815 m_update_physics = startupConfig.GetInt( "UpdatePhysicsEveryNFrames", m_update_physics);
816 m_update_presences = startupConfig.GetInt( "UpdateAgentsEveryNFrames", m_update_presences);
817 m_update_terrain = startupConfig.GetInt( "UpdateTerrainEveryNFrames", m_update_terrain);
818 m_update_temp_cleaning = startupConfig.GetInt( "UpdateTempCleaningEveryNFrames", m_update_temp_cleaning);
819 SendPeriodicAppearanceUpdates = startupConfig.GetBoolean("SendPeriodicAppearanceUpdates", SendPeriodicAppearanceUpdates);
820 }
821 }
822 catch (Exception e)
823 {
824 m_log.Error("[SCENE]: Failed to load StartupConfig: " + e.ToString());
792 } 825 }
793 826
794 #endregion Region Config 827 #endregion Region Config
@@ -1215,7 +1248,22 @@ namespace OpenSim.Region.Framework.Scenes
1215 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat); 1248 //m_heartbeatTimer.Elapsed += new ElapsedEventHandler(Heartbeat);
1216 if (m_heartbeatThread != null) 1249 if (m_heartbeatThread != null)
1217 { 1250 {
1251 m_hbRestarts++;
1252 if(m_hbRestarts > 10)
1253 Environment.Exit(1);
1254 m_log.ErrorFormat("[SCENE]: Restarting heartbeat thread because it hasn't reported in in region {0}", RegionInfo.RegionName);
1255
1256//int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
1257//System.Diagnostics.Process proc = new System.Diagnostics.Process();
1258//proc.EnableRaisingEvents=false;
1259//proc.StartInfo.FileName = "/bin/kill";
1260//proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
1261//proc.Start();
1262//proc.WaitForExit();
1263//Thread.Sleep(1000);
1264//Environment.Exit(1);
1218 m_heartbeatThread.Abort(); 1265 m_heartbeatThread.Abort();
1266 Watchdog.AbortThread(m_heartbeatThread.ManagedThreadId);
1219 m_heartbeatThread = null; 1267 m_heartbeatThread = null;
1220 } 1268 }
1221// m_lastUpdate = Util.EnvironmentTickCount(); 1269// m_lastUpdate = Util.EnvironmentTickCount();
@@ -1363,10 +1411,12 @@ namespace OpenSim.Region.Framework.Scenes
1363 int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS; 1411 int tmpPhysicsMS, tmpPhysicsMS2, tmpAgentMS, tmpTempOnRezMS, evMS, backMS, terMS;
1364 int previousFrameTick; 1412 int previousFrameTick;
1365 int maintc; 1413 int maintc;
1414 int sleepMS;
1415 int framestart;
1366 1416
1367 while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) 1417 while (!m_shuttingDown && (endFrame == null || Frame < endFrame))
1368 { 1418 {
1369 maintc = Util.EnvironmentTickCount(); 1419 framestart = Util.EnvironmentTickCount();
1370 ++Frame; 1420 ++Frame;
1371 1421
1372// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName); 1422// m_log.DebugFormat("[SCENE]: Processing frame {0} in {1}", Frame, RegionInfo.RegionName);
@@ -1454,7 +1504,7 @@ namespace OpenSim.Region.Framework.Scenes
1454 // landMS = Util.EnvironmentTickCountSubtract(ldMS); 1504 // landMS = Util.EnvironmentTickCountSubtract(ldMS);
1455 //} 1505 //}
1456 1506
1457 frameMS = Util.EnvironmentTickCountSubtract(maintc); 1507 // frameMS = Util.EnvironmentTickCountSubtract(maintc);
1458 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS; 1508 otherMS = tempOnRezMS + eventMS + backupMS + terrainMS + landMS;
1459 1509
1460 // if (Frame%m_update_avatars == 0) 1510 // if (Frame%m_update_avatars == 0)
@@ -1465,7 +1515,7 @@ namespace OpenSim.Region.Framework.Scenes
1465 1515
1466 // frameMS currently records work frame times, not total frame times (work + any required sleep to 1516 // frameMS currently records work frame times, not total frame times (work + any required sleep to
1467 // reach min frame time. 1517 // reach min frame time.
1468 StatsReporter.addFrameMS(frameMS); 1518 // StatsReporter.addFrameMS(frameMS);
1469 1519
1470 StatsReporter.addAgentMS(agentMS); 1520 StatsReporter.addAgentMS(agentMS);
1471 StatsReporter.addPhysicsMS(physicsMS + physicsMS2); 1521 StatsReporter.addPhysicsMS(physicsMS + physicsMS2);
@@ -1521,12 +1571,22 @@ namespace OpenSim.Region.Framework.Scenes
1521 1571
1522 previousFrameTick = m_lastFrameTick; 1572 previousFrameTick = m_lastFrameTick;
1523 m_lastFrameTick = Util.EnvironmentTickCount(); 1573 m_lastFrameTick = Util.EnvironmentTickCount();
1524 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, maintc); 1574 maintc = Util.EnvironmentTickCountSubtract(m_lastFrameTick, framestart);
1525 maintc = (int)(MinFrameTime * 1000) - maintc; 1575 maintc = (int)(MinFrameTime * 1000) - maintc;
1526 1576
1577 m_firstHeartbeat = false;
1578
1579
1580 sleepMS = Util.EnvironmentTickCount();
1581
1527 if (maintc > 0) 1582 if (maintc > 0)
1528 Thread.Sleep(maintc); 1583 Thread.Sleep(maintc);
1529 1584
1585 sleepMS = Util.EnvironmentTickCountSubtract(sleepMS);
1586 frameMS = Util.EnvironmentTickCountSubtract(framestart);
1587 StatsReporter.addSleepMS(sleepMS);
1588 StatsReporter.addFrameMS(frameMS);
1589
1530 // Optionally warn if a frame takes double the amount of time that it should. 1590 // Optionally warn if a frame takes double the amount of time that it should.
1531 if (DebugUpdates 1591 if (DebugUpdates
1532 && Util.EnvironmentTickCountSubtract( 1592 && Util.EnvironmentTickCountSubtract(
@@ -1553,9 +1613,9 @@ namespace OpenSim.Region.Framework.Scenes
1553 1613
1554 private void CheckAtTargets() 1614 private void CheckAtTargets()
1555 { 1615 {
1556 Dictionary<UUID, SceneObjectGroup>.ValueCollection objs; 1616 List<SceneObjectGroup> objs = new List<SceneObjectGroup>();
1557 lock (m_groupsWithTargets) 1617 lock (m_groupsWithTargets)
1558 objs = m_groupsWithTargets.Values; 1618 objs = new List<SceneObjectGroup>(m_groupsWithTargets.Values);
1559 1619
1560 foreach (SceneObjectGroup entry in objs) 1620 foreach (SceneObjectGroup entry in objs)
1561 entry.checkAtTargets(); 1621 entry.checkAtTargets();
@@ -1636,7 +1696,7 @@ namespace OpenSim.Region.Framework.Scenes
1636 msg.fromAgentName = "Server"; 1696 msg.fromAgentName = "Server";
1637 msg.dialog = (byte)19; // Object msg 1697 msg.dialog = (byte)19; // Object msg
1638 msg.fromGroup = false; 1698 msg.fromGroup = false;
1639 msg.offline = (byte)0; 1699 msg.offline = (byte)1;
1640 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1700 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1641 msg.Position = Vector3.Zero; 1701 msg.Position = Vector3.Zero;
1642 msg.RegionID = RegionInfo.RegionID.Guid; 1702 msg.RegionID = RegionInfo.RegionID.Guid;
@@ -1858,6 +1918,19 @@ namespace OpenSim.Region.Framework.Scenes
1858 EventManager.TriggerPrimsLoaded(this); 1918 EventManager.TriggerPrimsLoaded(this);
1859 } 1919 }
1860 1920
1921 public bool SuportsRayCastFiltered()
1922 {
1923 if (PhysicsScene == null)
1924 return false;
1925 return PhysicsScene.SuportsRaycastWorldFiltered();
1926 }
1927
1928 public object RayCastFiltered(Vector3 position, Vector3 direction, float length, int Count, RayFilterFlags filter)
1929 {
1930 if (PhysicsScene == null)
1931 return null;
1932 return PhysicsScene.RaycastWorld(position, direction, length, Count,filter);
1933 }
1861 1934
1862 /// <summary> 1935 /// <summary>
1863 /// Gets a new rez location based on the raycast and the size of the object that is being rezzed. 1936 /// Gets a new rez location based on the raycast and the size of the object that is being rezzed.
@@ -1874,14 +1947,24 @@ namespace OpenSim.Region.Framework.Scenes
1874 /// <returns></returns> 1947 /// <returns></returns>
1875 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter) 1948 public Vector3 GetNewRezLocation(Vector3 RayStart, Vector3 RayEnd, UUID RayTargetID, Quaternion rot, byte bypassRayCast, byte RayEndIsIntersection, bool frontFacesOnly, Vector3 scale, bool FaceCenter)
1876 { 1949 {
1950
1951 float wheight = (float)RegionInfo.RegionSettings.WaterHeight;
1952 Vector3 wpos = Vector3.Zero;
1953 // Check for water surface intersection from above
1954 if ( (RayStart.Z > wheight) && (RayEnd.Z < wheight) )
1955 {
1956 float ratio = (RayStart.Z - wheight) / (RayStart.Z - RayEnd.Z);
1957 wpos.X = RayStart.X - (ratio * (RayStart.X - RayEnd.X));
1958 wpos.Y = RayStart.Y - (ratio * (RayStart.Y - RayEnd.Y));
1959 wpos.Z = wheight;
1960 }
1961
1877 Vector3 pos = Vector3.Zero; 1962 Vector3 pos = Vector3.Zero;
1878 if (RayEndIsIntersection == (byte)1) 1963 if (RayEndIsIntersection == (byte)1)
1879 { 1964 {
1880 pos = RayEnd; 1965 pos = RayEnd;
1881 return pos;
1882 } 1966 }
1883 1967 else if (RayTargetID != UUID.Zero)
1884 if (RayTargetID != UUID.Zero)
1885 { 1968 {
1886 SceneObjectPart target = GetSceneObjectPart(RayTargetID); 1969 SceneObjectPart target = GetSceneObjectPart(RayTargetID);
1887 1970
@@ -1903,7 +1986,7 @@ namespace OpenSim.Region.Framework.Scenes
1903 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter); 1986 EntityIntersection ei = target.TestIntersectionOBB(NewRay, Quaternion.Identity, frontFacesOnly, FaceCenter);
1904 1987
1905 // Un-comment out the following line to Get Raytrace results printed to the console. 1988 // Un-comment out the following line to Get Raytrace results printed to the console.
1906 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString()); 1989 // m_log.Info("[RAYTRACERESULTS]: Hit:" + ei.HitTF.ToString() + " Point: " + ei.ipoint.ToString() + " Normal: " + ei.normal.ToString());
1907 float ScaleOffset = 0.5f; 1990 float ScaleOffset = 0.5f;
1908 1991
1909 // If we hit something 1992 // If we hit something
@@ -1926,13 +2009,10 @@ namespace OpenSim.Region.Framework.Scenes
1926 //pos.Z -= 0.25F; 2009 //pos.Z -= 0.25F;
1927 2010
1928 } 2011 }
1929
1930 return pos;
1931 } 2012 }
1932 else 2013 else
1933 { 2014 {
1934 // We don't have a target here, so we're going to raytrace all the objects in the scene. 2015 // We don't have a target here, so we're going to raytrace all the objects in the scene.
1935
1936 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false); 2016 EntityIntersection ei = m_sceneGraph.GetClosestIntersectingPrim(new Ray(AXOrigin, AXdirection), true, false);
1937 2017
1938 // Un-comment the following line to print the raytrace results to the console. 2018 // Un-comment the following line to print the raytrace results to the console.
@@ -1941,13 +2021,12 @@ namespace OpenSim.Region.Framework.Scenes
1941 if (ei.HitTF) 2021 if (ei.HitTF)
1942 { 2022 {
1943 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z); 2023 pos = new Vector3(ei.ipoint.X, ei.ipoint.Y, ei.ipoint.Z);
1944 } else 2024 }
2025 else
1945 { 2026 {
1946 // fall back to our stupid functionality 2027 // fall back to our stupid functionality
1947 pos = RayEnd; 2028 pos = RayEnd;
1948 } 2029 }
1949
1950 return pos;
1951 } 2030 }
1952 } 2031 }
1953 else 2032 else
@@ -1958,8 +2037,12 @@ namespace OpenSim.Region.Framework.Scenes
1958 //increase height so its above the ground. 2037 //increase height so its above the ground.
1959 //should be getting the normal of the ground at the rez point and using that? 2038 //should be getting the normal of the ground at the rez point and using that?
1960 pos.Z += scale.Z / 2f; 2039 pos.Z += scale.Z / 2f;
1961 return pos; 2040// return pos;
1962 } 2041 }
2042
2043 // check against posible water intercept
2044 if (wpos.Z > pos.Z) pos = wpos;
2045 return pos;
1963 } 2046 }
1964 2047
1965 2048
@@ -2049,7 +2132,10 @@ namespace OpenSim.Region.Framework.Scenes
2049 public bool AddRestoredSceneObject( 2132 public bool AddRestoredSceneObject(
2050 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 2133 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
2051 { 2134 {
2052 return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); 2135 bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates);
2136 if (result)
2137 sceneObject.IsDeleted = false;
2138 return result;
2053 } 2139 }
2054 2140
2055 /// <summary> 2141 /// <summary>
@@ -2141,6 +2227,15 @@ namespace OpenSim.Region.Framework.Scenes
2141 /// </summary> 2227 /// </summary>
2142 public void DeleteAllSceneObjects() 2228 public void DeleteAllSceneObjects()
2143 { 2229 {
2230 DeleteAllSceneObjects(false);
2231 }
2232
2233 /// <summary>
2234 /// Delete every object from the scene. This does not include attachments worn by avatars.
2235 /// </summary>
2236 public void DeleteAllSceneObjects(bool exceptNoCopy)
2237 {
2238 List<SceneObjectGroup> toReturn = new List<SceneObjectGroup>();
2144 lock (Entities) 2239 lock (Entities)
2145 { 2240 {
2146 EntityBase[] entities = Entities.GetEntities(); 2241 EntityBase[] entities = Entities.GetEntities();
@@ -2149,11 +2244,24 @@ namespace OpenSim.Region.Framework.Scenes
2149 if (e is SceneObjectGroup) 2244 if (e is SceneObjectGroup)
2150 { 2245 {
2151 SceneObjectGroup sog = (SceneObjectGroup)e; 2246 SceneObjectGroup sog = (SceneObjectGroup)e;
2152 if (!sog.IsAttachment) 2247 if (sog != null && !sog.IsAttachment)
2153 DeleteSceneObject((SceneObjectGroup)e, false); 2248 {
2249 if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0))
2250 {
2251 DeleteSceneObject((SceneObjectGroup)e, false);
2252 }
2253 else
2254 {
2255 toReturn.Add((SceneObjectGroup)e);
2256 }
2257 }
2154 } 2258 }
2155 } 2259 }
2156 } 2260 }
2261 if (toReturn.Count > 0)
2262 {
2263 returnObjects(toReturn.ToArray(), UUID.Zero);
2264 }
2157 } 2265 }
2158 2266
2159 /// <summary> 2267 /// <summary>
@@ -2188,6 +2296,8 @@ namespace OpenSim.Region.Framework.Scenes
2188 } 2296 }
2189 2297
2190 group.DeleteGroupFromScene(silent); 2298 group.DeleteGroupFromScene(silent);
2299 if (!silent)
2300 SendKillObject(new List<uint>() { group.LocalId });
2191 2301
2192// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID); 2302// m_log.DebugFormat("[SCENE]: Exit DeleteSceneObject() for {0} {1}", group.Name, group.UUID);
2193 } 2303 }
@@ -2477,6 +2587,8 @@ namespace OpenSim.Region.Framework.Scenes
2477 2587
2478 if (newPosition != Vector3.Zero) 2588 if (newPosition != Vector3.Zero)
2479 newObject.RootPart.GroupPosition = newPosition; 2589 newObject.RootPart.GroupPosition = newPosition;
2590 if (newObject.RootPart.KeyframeMotion != null)
2591 newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2480 2592
2481 if (!AddSceneObject(newObject)) 2593 if (!AddSceneObject(newObject))
2482 { 2594 {
@@ -2545,10 +2657,17 @@ namespace OpenSim.Region.Framework.Scenes
2545 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns> 2657 /// <returns>True if the SceneObjectGroup was added, False if it was not</returns>
2546 public bool AddSceneObject(SceneObjectGroup sceneObject) 2658 public bool AddSceneObject(SceneObjectGroup sceneObject)
2547 { 2659 {
2660 if (sceneObject.OwnerID == UUID.Zero)
2661 {
2662 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero", sceneObject.UUID);
2663 return false;
2664 }
2665
2548 // If the user is banned, we won't let any of their objects 2666 // If the user is banned, we won't let any of their objects
2549 // enter. Period. 2667 // enter. Period.
2550 // 2668 //
2551 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID)) 2669 int flags = GetUserFlags(sceneObject.OwnerID);
2670 if (m_regInfo.EstateSettings.IsBanned(sceneObject.OwnerID, flags))
2552 { 2671 {
2553 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID); 2672 m_log.InfoFormat("[INTERREGION]: Denied prim crossing for banned avatar {0}", sceneObject.OwnerID);
2554 2673
@@ -2594,12 +2713,23 @@ namespace OpenSim.Region.Framework.Scenes
2594 } 2713 }
2595 else 2714 else
2596 { 2715 {
2716 m_log.DebugFormat("[SCENE]: Attachment {0} arrived and scene presence was not found, setting to temp", sceneObject.UUID);
2597 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2717 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2598 RootPrim.AddFlag(PrimFlags.TemporaryOnRez); 2718 RootPrim.AddFlag(PrimFlags.TemporaryOnRez);
2599 } 2719 }
2720 if (sceneObject.OwnerID == UUID.Zero)
2721 {
2722 m_log.ErrorFormat("[SCENE]: Owner ID for {0} was zero after attachment processing. BUG!", sceneObject.UUID);
2723 return false;
2724 }
2600 } 2725 }
2601 else 2726 else
2602 { 2727 {
2728 if (sceneObject.OwnerID == UUID.Zero)
2729 {
2730 m_log.ErrorFormat("[SCENE]: Owner ID for non-attachment {0} was zero", sceneObject.UUID);
2731 return false;
2732 }
2603 AddRestoredSceneObject(sceneObject, true, false); 2733 AddRestoredSceneObject(sceneObject, true, false);
2604 2734
2605 if (!Permissions.CanObjectEntry(sceneObject.UUID, 2735 if (!Permissions.CanObjectEntry(sceneObject.UUID,
@@ -2628,6 +2758,24 @@ namespace OpenSim.Region.Framework.Scenes
2628 return 2; // StateSource.PrimCrossing 2758 return 2; // StateSource.PrimCrossing
2629 } 2759 }
2630 2760
2761 public int GetUserFlags(UUID user)
2762 {
2763 //Unfortunately the SP approach means that the value is cached until region is restarted
2764 /*
2765 ScenePresence sp;
2766 if (TryGetScenePresence(user, out sp))
2767 {
2768 return sp.UserFlags;
2769 }
2770 else
2771 {
2772 */
2773 UserAccount uac = UserAccountService.GetUserAccount(RegionInfo.ScopeID, user);
2774 if (uac == null)
2775 return 0;
2776 return uac.UserFlags;
2777 //}
2778 }
2631 #endregion 2779 #endregion
2632 2780
2633 #region Add/Remove Avatar Methods 2781 #region Add/Remove Avatar Methods
@@ -2641,7 +2789,7 @@ namespace OpenSim.Region.Framework.Scenes
2641 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 2789 = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0
2642 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; 2790 || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0;
2643 2791
2644// CheckHeartbeat(); 2792 CheckHeartbeat();
2645 2793
2646 ScenePresence sp = GetScenePresence(client.AgentId); 2794 ScenePresence sp = GetScenePresence(client.AgentId);
2647 2795
@@ -2695,7 +2843,13 @@ namespace OpenSim.Region.Framework.Scenes
2695 2843
2696 EventManager.TriggerOnNewClient(client); 2844 EventManager.TriggerOnNewClient(client);
2697 if (vialogin) 2845 if (vialogin)
2846 {
2698 EventManager.TriggerOnClientLogin(client); 2847 EventManager.TriggerOnClientLogin(client);
2848 // Send initial parcel data
2849 Vector3 pos = sp.AbsolutePosition;
2850 ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y);
2851 land.SendLandUpdateToClient(client);
2852 }
2699 2853
2700 return sp; 2854 return sp;
2701 } 2855 }
@@ -2785,19 +2939,12 @@ namespace OpenSim.Region.Framework.Scenes
2785 // and the scene presence and the client, if they exist 2939 // and the scene presence and the client, if they exist
2786 try 2940 try
2787 { 2941 {
2788 // We need to wait for the client to make UDP contact first. 2942 ScenePresence sp = GetScenePresence(agentID);
2789 // It's the UDP contact that creates the scene presence 2943 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2790 ScenePresence sp = WaitGetScenePresence(agentID); 2944
2791 if (sp != null) 2945 if (sp != null)
2792 {
2793 PresenceService.LogoutAgent(sp.ControllingClient.SessionId);
2794
2795 sp.ControllingClient.Close(); 2946 sp.ControllingClient.Close();
2796 } 2947
2797 else
2798 {
2799 m_log.WarnFormat("[SCENE]: Could not find scene presence for {0}", agentID);
2800 }
2801 // BANG! SLASH! 2948 // BANG! SLASH!
2802 m_authenticateHandler.RemoveCircuit(agentID); 2949 m_authenticateHandler.RemoveCircuit(agentID);
2803 2950
@@ -2842,6 +2989,8 @@ namespace OpenSim.Region.Framework.Scenes
2842 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition; 2989 client.OnUpdatePrimGroupPosition += m_sceneGraph.UpdatePrimGroupPosition;
2843 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition; 2990 client.OnUpdatePrimSinglePosition += m_sceneGraph.UpdatePrimSinglePosition;
2844 2991
2992 client.onClientChangeObject += m_sceneGraph.ClientChangeObject;
2993
2845 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation; 2994 client.OnUpdatePrimGroupRotation += m_sceneGraph.UpdatePrimGroupRotation;
2846 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation; 2995 client.OnUpdatePrimGroupMouseRotation += m_sceneGraph.UpdatePrimGroupRotation;
2847 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation; 2996 client.OnUpdatePrimSingleRotation += m_sceneGraph.UpdatePrimSingleRotation;
@@ -2898,6 +3047,7 @@ namespace OpenSim.Region.Framework.Scenes
2898 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory; 3047 client.OnFetchInventory += m_asyncInventorySender.HandleFetchInventory;
2899 client.OnUpdateInventoryItem += UpdateInventoryItemAsset; 3048 client.OnUpdateInventoryItem += UpdateInventoryItemAsset;
2900 client.OnCopyInventoryItem += CopyInventoryItem; 3049 client.OnCopyInventoryItem += CopyInventoryItem;
3050 client.OnMoveItemsAndLeaveCopy += MoveInventoryItemsLeaveCopy;
2901 client.OnMoveInventoryItem += MoveInventoryItem; 3051 client.OnMoveInventoryItem += MoveInventoryItem;
2902 client.OnRemoveInventoryItem += RemoveInventoryItem; 3052 client.OnRemoveInventoryItem += RemoveInventoryItem;
2903 client.OnRemoveInventoryFolder += RemoveInventoryFolder; 3053 client.OnRemoveInventoryFolder += RemoveInventoryFolder;
@@ -2969,6 +3119,8 @@ namespace OpenSim.Region.Framework.Scenes
2969 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition; 3119 client.OnUpdatePrimGroupPosition -= m_sceneGraph.UpdatePrimGroupPosition;
2970 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition; 3120 client.OnUpdatePrimSinglePosition -= m_sceneGraph.UpdatePrimSinglePosition;
2971 3121
3122 client.onClientChangeObject -= m_sceneGraph.ClientChangeObject;
3123
2972 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3124 client.OnUpdatePrimGroupRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2973 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation; 3125 client.OnUpdatePrimGroupMouseRotation -= m_sceneGraph.UpdatePrimGroupRotation;
2974 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation; 3126 client.OnUpdatePrimSingleRotation -= m_sceneGraph.UpdatePrimSingleRotation;
@@ -3071,7 +3223,7 @@ namespace OpenSim.Region.Framework.Scenes
3071 /// </summary> 3223 /// </summary>
3072 /// <param name="agentId">The avatar's Unique ID</param> 3224 /// <param name="agentId">The avatar's Unique ID</param>
3073 /// <param name="client">The IClientAPI for the client</param> 3225 /// <param name="client">The IClientAPI for the client</param>
3074 public virtual void TeleportClientHome(UUID agentId, IClientAPI client) 3226 public virtual bool TeleportClientHome(UUID agentId, IClientAPI client)
3075 { 3227 {
3076 if (EntityTransferModule != null) 3228 if (EntityTransferModule != null)
3077 { 3229 {
@@ -3082,6 +3234,7 @@ namespace OpenSim.Region.Framework.Scenes
3082 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active"); 3234 m_log.DebugFormat("[SCENE]: Unable to teleport user home: no AgentTransferModule is active");
3083 client.SendTeleportFailed("Unable to perform teleports on this simulator."); 3235 client.SendTeleportFailed("Unable to perform teleports on this simulator.");
3084 } 3236 }
3237 return false;
3085 } 3238 }
3086 3239
3087 /// <summary> 3240 /// <summary>
@@ -3191,6 +3344,16 @@ namespace OpenSim.Region.Framework.Scenes
3191 /// <param name="flags"></param> 3344 /// <param name="flags"></param>
3192 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags) 3345 public virtual void SetHomeRezPoint(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint flags)
3193 { 3346 {
3347 //Add half the avatar's height so that the user doesn't fall through prims
3348 ScenePresence presence;
3349 if (TryGetScenePresence(remoteClient.AgentId, out presence))
3350 {
3351 if (presence.Appearance != null)
3352 {
3353 position.Z = position.Z + (presence.Appearance.AvatarHeight / 2);
3354 }
3355 }
3356
3194 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt)) 3357 if (GridUserService != null && GridUserService.SetHome(remoteClient.AgentId.ToString(), RegionInfo.RegionID, position, lookAt))
3195 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot. 3358 // FUBAR ALERT: this needs to be "Home position set." so the viewer saves a home-screenshot.
3196 m_dialogModule.SendAlertToUser(remoteClient, "Home position set."); 3359 m_dialogModule.SendAlertToUser(remoteClient, "Home position set.");
@@ -3259,8 +3422,9 @@ namespace OpenSim.Region.Framework.Scenes
3259 regions.Remove(RegionInfo.RegionHandle); 3422 regions.Remove(RegionInfo.RegionHandle);
3260 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); 3423 m_sceneGridService.SendCloseChildAgentConnections(agentID, regions);
3261 } 3424 }
3262 3425 m_log.Debug("[Scene] Beginning ClientClosed");
3263 m_eventManager.TriggerClientClosed(agentID, this); 3426 m_eventManager.TriggerClientClosed(agentID, this);
3427 m_log.Debug("[Scene] Finished ClientClosed");
3264 } 3428 }
3265 catch (NullReferenceException) 3429 catch (NullReferenceException)
3266 { 3430 {
@@ -3322,9 +3486,10 @@ namespace OpenSim.Region.Framework.Scenes
3322 { 3486 {
3323 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace); 3487 m_log.ErrorFormat("[SCENE] Scene.cs:RemoveClient exception {0}{1}", e.Message, e.StackTrace);
3324 } 3488 }
3325 3489 m_log.Debug("[Scene] Done. Firing RemoveCircuit");
3326 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); 3490 m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode);
3327// CleanDroppedAttachments(); 3491// CleanDroppedAttachments();
3492 m_log.Debug("[Scene] The avatar has left the building");
3328 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 3493 //m_log.InfoFormat("[SCENE] Memory pre GC {0}", System.GC.GetTotalMemory(false));
3329 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true)); 3494 //m_log.InfoFormat("[SCENE] Memory post GC {0}", System.GC.GetTotalMemory(true));
3330 } 3495 }
@@ -3459,13 +3624,16 @@ namespace OpenSim.Region.Framework.Scenes
3459 sp = null; 3624 sp = null;
3460 } 3625 }
3461 3626
3462 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3463 3627
3464 //On login test land permisions 3628 //On login test land permisions
3465 if (vialogin) 3629 if (vialogin)
3466 { 3630 {
3467 if (land != null && !TestLandRestrictions(agent, land, out reason)) 3631 IUserAccountCacheModule cache = RequestModuleInterface<IUserAccountCacheModule>();
3632 if (cache != null)
3633 cache.Remove(agent.firstname + " " + agent.lastname);
3634 if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y))
3468 { 3635 {
3636 m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString());
3469 return false; 3637 return false;
3470 } 3638 }
3471 } 3639 }
@@ -3488,9 +3656,15 @@ namespace OpenSim.Region.Framework.Scenes
3488 3656
3489 try 3657 try
3490 { 3658 {
3491 if (!AuthorizeUser(agent, out reason)) 3659 // Always check estate if this is a login. Always
3492 return false; 3660 // check if banned regions are to be blacked out.
3493 } catch (Exception e) 3661 if (vialogin || (!m_seeIntoBannedRegion))
3662 {
3663 if (!AuthorizeUser(agent, out reason))
3664 return false;
3665 }
3666 }
3667 catch (Exception e)
3494 { 3668 {
3495 m_log.ErrorFormat( 3669 m_log.ErrorFormat(
3496 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); 3670 "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace);
@@ -3621,6 +3795,8 @@ namespace OpenSim.Region.Framework.Scenes
3621 } 3795 }
3622 3796
3623 // Honor parcel landing type and position. 3797 // Honor parcel landing type and position.
3798 /*
3799 ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y);
3624 if (land != null) 3800 if (land != null)
3625 { 3801 {
3626 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) 3802 if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero)
@@ -3628,25 +3804,34 @@ namespace OpenSim.Region.Framework.Scenes
3628 agent.startpos = land.LandData.UserLocation; 3804 agent.startpos = land.LandData.UserLocation;
3629 } 3805 }
3630 } 3806 }
3807 */// This is now handled properly in ScenePresence.MakeRootAgent
3631 } 3808 }
3632 3809
3633 return true; 3810 return true;
3634 } 3811 }
3635 3812
3636 private bool TestLandRestrictions(AgentCircuitData agent, ILandObject land, out string reason) 3813 public bool TestLandRestrictions(UUID agentID, out string reason, ref float posX, ref float posY)
3637 { 3814 {
3638 bool banned = land.IsBannedFromLand(agent.AgentID); 3815 reason = String.Empty;
3639 bool restricted = land.IsRestrictedFromLand(agent.AgentID); 3816 if (Permissions.IsGod(agentID))
3817 return true;
3818
3819 ILandObject land = LandChannel.GetLandObject(posX, posY);
3820 if (land == null)
3821 return false;
3822
3823 bool banned = land.IsBannedFromLand(agentID);
3824 bool restricted = land.IsRestrictedFromLand(agentID);
3640 3825
3641 if (banned || restricted) 3826 if (banned || restricted)
3642 { 3827 {
3643 ILandObject nearestParcel = GetNearestAllowedParcel(agent.AgentID, agent.startpos.X, agent.startpos.Y); 3828 ILandObject nearestParcel = GetNearestAllowedParcel(agentID, posX, posY);
3644 if (nearestParcel != null) 3829 if (nearestParcel != null)
3645 { 3830 {
3646 //Move agent to nearest allowed 3831 //Move agent to nearest allowed
3647 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); 3832 Vector3 newPosition = GetParcelCenterAtGround(nearestParcel);
3648 agent.startpos.X = newPosition.X; 3833 posX = newPosition.X;
3649 agent.startpos.Y = newPosition.Y; 3834 posY = newPosition.Y;
3650 } 3835 }
3651 else 3836 else
3652 { 3837 {
@@ -3708,7 +3893,7 @@ namespace OpenSim.Region.Framework.Scenes
3708 3893
3709 if (!m_strictAccessControl) return true; 3894 if (!m_strictAccessControl) return true;
3710 if (Permissions.IsGod(agent.AgentID)) return true; 3895 if (Permissions.IsGod(agent.AgentID)) return true;
3711 3896
3712 if (AuthorizationService != null) 3897 if (AuthorizationService != null)
3713 { 3898 {
3714 if (!AuthorizationService.IsAuthorizedForRegion( 3899 if (!AuthorizationService.IsAuthorizedForRegion(
@@ -3723,7 +3908,7 @@ namespace OpenSim.Region.Framework.Scenes
3723 3908
3724 if (m_regInfo.EstateSettings != null) 3909 if (m_regInfo.EstateSettings != null)
3725 { 3910 {
3726 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) 3911 if (m_regInfo.EstateSettings.IsBanned(agent.AgentID,0))
3727 { 3912 {
3728 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", 3913 m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist",
3729 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); 3914 agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName);
@@ -3913,6 +4098,15 @@ namespace OpenSim.Region.Framework.Scenes
3913 4098
3914 // XPTO: if this agent is not allowed here as root, always return false 4099 // XPTO: if this agent is not allowed here as root, always return false
3915 4100
4101 // We have to wait until the viewer contacts this region after receiving EAC.
4102 // That calls AddNewClient, which finally creates the ScenePresence
4103 int flags = GetUserFlags(cAgentData.AgentID);
4104 if (m_regInfo.EstateSettings.IsBanned(cAgentData.AgentID, flags))
4105 {
4106 m_log.DebugFormat("[SCENE]: Denying root agent entry to {0}: banned", cAgentData.AgentID);
4107 return false;
4108 }
4109
3916 // TODO: This check should probably be in QueryAccess(). 4110 // TODO: This check should probably be in QueryAccess().
3917 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2); 4111 ILandObject nearestParcel = GetNearestAllowedParcel(cAgentData.AgentID, Constants.RegionSize / 2, Constants.RegionSize / 2);
3918 if (nearestParcel == null) 4112 if (nearestParcel == null)
@@ -4006,12 +4200,22 @@ namespace OpenSim.Region.Framework.Scenes
4006 return false; 4200 return false;
4007 } 4201 }
4008 4202
4203 public bool IncomingCloseAgent(UUID agentID)
4204 {
4205 return IncomingCloseAgent(agentID, false);
4206 }
4207
4208 public bool IncomingCloseChildAgent(UUID agentID)
4209 {
4210 return IncomingCloseAgent(agentID, true);
4211 }
4212
4009 /// <summary> 4213 /// <summary>
4010 /// Tell a single agent to disconnect from the region. 4214 /// Tell a single agent to disconnect from the region.
4011 /// </summary> 4215 /// </summary>
4012 /// <param name="regionHandle"></param>
4013 /// <param name="agentID"></param> 4216 /// <param name="agentID"></param>
4014 public bool IncomingCloseAgent(UUID agentID) 4217 /// <param name="childOnly"></param>
4218 public bool IncomingCloseAgent(UUID agentID, bool childOnly)
4015 { 4219 {
4016 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); 4220 //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID);
4017 4221
@@ -4023,7 +4227,7 @@ namespace OpenSim.Region.Framework.Scenes
4023 { 4227 {
4024 m_sceneGraph.removeUserCount(false); 4228 m_sceneGraph.removeUserCount(false);
4025 } 4229 }
4026 else 4230 else if (!childOnly)
4027 { 4231 {
4028 m_sceneGraph.removeUserCount(true); 4232 m_sceneGraph.removeUserCount(true);
4029 } 4233 }
@@ -4039,9 +4243,12 @@ namespace OpenSim.Region.Framework.Scenes
4039 } 4243 }
4040 else 4244 else
4041 presence.ControllingClient.SendShutdownConnectionNotice(); 4245 presence.ControllingClient.SendShutdownConnectionNotice();
4246 presence.ControllingClient.Close(false);
4247 }
4248 else if (!childOnly)
4249 {
4250 presence.ControllingClient.Close(true);
4042 } 4251 }
4043
4044 presence.ControllingClient.Close();
4045 return true; 4252 return true;
4046 } 4253 }
4047 4254
@@ -4627,35 +4834,81 @@ namespace OpenSim.Region.Framework.Scenes
4627 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID); 4834 SimulationDataService.RemoveObject(uuid, m_regInfo.RegionID);
4628 } 4835 }
4629 4836
4630 public int GetHealth() 4837 public int GetHealth(out int flags, out string message)
4631 { 4838 {
4632 // Returns: 4839 // Returns:
4633 // 1 = sim is up and accepting http requests. The heartbeat has 4840 // 1 = sim is up and accepting http requests. The heartbeat has
4634 // stopped and the sim is probably locked up, but a remote 4841 // stopped and the sim is probably locked up, but a remote
4635 // admin restart may succeed 4842 // admin restart may succeed
4636 // 4843 //
4637 // 2 = Sim is up and the heartbeat is running. The sim is likely 4844 // 2 = Sim is up and the heartbeat is running. The sim is likely
4638 // usable for people within and logins _may_ work 4845 // usable for people within
4639 // 4846 //
4640 // 3 = We have seen a new user enter within the past 4 minutes 4847 // 3 = Sim is up and one packet thread is running. Sim is
4848 // unstable and will not accept new logins
4849 //
4850 // 4 = Sim is up and both packet threads are running. Sim is
4851 // likely usable
4852 //
4853 // 5 = We have seen a new user enter within the past 4 minutes
4641 // which can be seen as positive confirmation of sim health 4854 // which can be seen as positive confirmation of sim health
4642 // 4855 //
4856
4857 flags = 0;
4858 message = String.Empty;
4859
4860 CheckHeartbeat();
4861
4862 if (m_firstHeartbeat || (m_lastIncoming == 0 && m_lastOutgoing == 0))
4863 {
4864 // We're still starting
4865 // 0 means "in startup", it can't happen another way, since
4866 // to get here, we must be able to accept http connections
4867 return 0;
4868 }
4869
4643 int health=1; // Start at 1, means we're up 4870 int health=1; // Start at 1, means we're up
4644 4871
4645 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) 4872 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000)
4646 health += 1; 4873 {
4874 health+=1;
4875 flags |= 1;
4876 }
4877
4878 if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000)
4879 {
4880 health+=1;
4881 flags |= 2;
4882 }
4883
4884 if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000)
4885 {
4886 health+=1;
4887 flags |= 4;
4888 }
4647 else 4889 else
4890 {
4891int pid = System.Diagnostics.Process.GetCurrentProcess().Id;
4892System.Diagnostics.Process proc = new System.Diagnostics.Process();
4893proc.EnableRaisingEvents=false;
4894proc.StartInfo.FileName = "/bin/kill";
4895proc.StartInfo.Arguments = "-QUIT " + pid.ToString();
4896proc.Start();
4897proc.WaitForExit();
4898Thread.Sleep(1000);
4899Environment.Exit(1);
4900 }
4901
4902 if (flags != 7)
4648 return health; 4903 return health;
4649 4904
4650 // A login in the last 4 mins? We can't be doing too badly 4905 // A login in the last 4 mins? We can't be doing too badly
4651 // 4906 //
4652 if ((Util.EnvironmentTickCountSubtract(m_LastLogin)) < 240000) 4907 if (Util.EnvironmentTickCountSubtract(m_LastLogin) < 240000)
4653 health++; 4908 health++;
4654 else 4909 else
4655 return health; 4910 return health;
4656 4911
4657// CheckHeartbeat();
4658
4659 return health; 4912 return health;
4660 } 4913 }
4661 4914
@@ -4743,7 +4996,7 @@ namespace OpenSim.Region.Framework.Scenes
4743 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0); 4996 bool wasUsingPhysics = ((jointProxyObject.Flags & PrimFlags.Physics) != 0);
4744 if (wasUsingPhysics) 4997 if (wasUsingPhysics)
4745 { 4998 {
4746 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 4999 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
4747 } 5000 }
4748 } 5001 }
4749 5002
@@ -4842,14 +5095,14 @@ namespace OpenSim.Region.Framework.Scenes
4842 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z; 5095 return (((vsn.X * xdiff) + (vsn.Y * ydiff)) / (-1 * vsn.Z)) + p0.Z;
4843 } 5096 }
4844 5097
4845// private void CheckHeartbeat() 5098 private void CheckHeartbeat()
4846// { 5099 {
4847// if (m_firstHeartbeat) 5100 if (m_firstHeartbeat)
4848// return; 5101 return;
4849// 5102
4850// if (Util.EnvironmentTickCountSubtract(m_lastFrameTick) > 2000) 5103 if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) > 5000)
4851// StartTimer(); 5104 Start();
4852// } 5105 }
4853 5106
4854 public override ISceneObject DeserializeObject(string representation) 5107 public override ISceneObject DeserializeObject(string representation)
4855 { 5108 {
@@ -4861,9 +5114,14 @@ namespace OpenSim.Region.Framework.Scenes
4861 get { return m_allowScriptCrossings; } 5114 get { return m_allowScriptCrossings; }
4862 } 5115 }
4863 5116
4864 public Vector3? GetNearestAllowedPosition(ScenePresence avatar) 5117 public Vector3 GetNearestAllowedPosition(ScenePresence avatar)
5118 {
5119 return GetNearestAllowedPosition(avatar, null);
5120 }
5121
5122 public Vector3 GetNearestAllowedPosition(ScenePresence avatar, ILandObject excludeParcel)
4865 { 5123 {
4866 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); 5124 ILandObject nearestParcel = GetNearestAllowedParcel(avatar.UUID, avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y, excludeParcel);
4867 5125
4868 if (nearestParcel != null) 5126 if (nearestParcel != null)
4869 { 5127 {
@@ -4872,10 +5130,7 @@ namespace OpenSim.Region.Framework.Scenes
4872 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5130 Vector3? nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4873 if (nearestPoint != null) 5131 if (nearestPoint != null)
4874 { 5132 {
4875// m_log.DebugFormat( 5133 Debug.WriteLine("Found a sane previous position based on velocity, sending them to: " + nearestPoint.ToString());
4876// "[SCENE]: Found a sane previous position based on velocity for {0}, sending them to {1} in {2}",
4877// avatar.Name, nearestPoint, nearestParcel.LandData.Name);
4878
4879 return nearestPoint.Value; 5134 return nearestPoint.Value;
4880 } 5135 }
4881 5136
@@ -4885,17 +5140,20 @@ namespace OpenSim.Region.Framework.Scenes
4885 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel); 5140 nearestPoint = GetNearestPointInParcelAlongDirectionFromPoint(avatar.AbsolutePosition, dir, nearestParcel);
4886 if (nearestPoint != null) 5141 if (nearestPoint != null)
4887 { 5142 {
4888// m_log.DebugFormat( 5143 Debug.WriteLine("They had a zero velocity, sending them to: " + nearestPoint.ToString());
4889// "[SCENE]: {0} had a zero velocity, sending them to {1}", avatar.Name, nearestPoint);
4890
4891 return nearestPoint.Value; 5144 return nearestPoint.Value;
4892 } 5145 }
4893 5146
4894 //Ultimate backup if we have no idea where they are 5147 ILandObject dest = LandChannel.GetLandObject(avatar.lastKnownAllowedPosition.X, avatar.lastKnownAllowedPosition.Y);
4895// m_log.DebugFormat( 5148 if (dest != excludeParcel)
4896// "[SCENE]: No idea where {0} is, sending them to {1}", avatar.Name, avatar.lastKnownAllowedPosition); 5149 {
5150 // Ultimate backup if we have no idea where they are and
5151 // the last allowed position was in another parcel
5152 Debug.WriteLine("Have no idea where they are, sending them to: " + avatar.lastKnownAllowedPosition.ToString());
5153 return avatar.lastKnownAllowedPosition;
5154 }
4897 5155
4898 return avatar.lastKnownAllowedPosition; 5156 // else fall through to region edge
4899 } 5157 }
4900 5158
4901 //Go to the edge, this happens in teleporting to a region with no available parcels 5159 //Go to the edge, this happens in teleporting to a region with no available parcels
@@ -4929,13 +5187,18 @@ namespace OpenSim.Region.Framework.Scenes
4929 5187
4930 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y) 5188 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y)
4931 { 5189 {
5190 return GetNearestAllowedParcel(avatarId, x, y, null);
5191 }
5192
5193 public ILandObject GetNearestAllowedParcel(UUID avatarId, float x, float y, ILandObject excludeParcel)
5194 {
4932 List<ILandObject> all = AllParcels(); 5195 List<ILandObject> all = AllParcels();
4933 float minParcelDistance = float.MaxValue; 5196 float minParcelDistance = float.MaxValue;
4934 ILandObject nearestParcel = null; 5197 ILandObject nearestParcel = null;
4935 5198
4936 foreach (var parcel in all) 5199 foreach (var parcel in all)
4937 { 5200 {
4938 if (!parcel.IsEitherBannedOrRestricted(avatarId)) 5201 if (!parcel.IsEitherBannedOrRestricted(avatarId) && parcel != excludeParcel)
4939 { 5202 {
4940 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y); 5203 float parcelDistance = GetParcelDistancefromPoint(parcel, x, y);
4941 if (parcelDistance < minParcelDistance) 5204 if (parcelDistance < minParcelDistance)
@@ -5177,7 +5440,55 @@ namespace OpenSim.Region.Framework.Scenes
5177 mapModule.GenerateMaptile(); 5440 mapModule.GenerateMaptile();
5178 } 5441 }
5179 5442
5180 private void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e) 5443// public void CleanDroppedAttachments()
5444// {
5445// List<SceneObjectGroup> objectsToDelete =
5446// new List<SceneObjectGroup>();
5447//
5448// lock (m_cleaningAttachments)
5449// {
5450// ForEachSOG(delegate (SceneObjectGroup grp)
5451// {
5452// if (grp.RootPart.Shape.PCode == 0 && grp.RootPart.Shape.State != 0 && (!objectsToDelete.Contains(grp)))
5453// {
5454// UUID agentID = grp.OwnerID;
5455// if (agentID == UUID.Zero)
5456// {
5457// objectsToDelete.Add(grp);
5458// return;
5459// }
5460//
5461// ScenePresence sp = GetScenePresence(agentID);
5462// if (sp == null)
5463// {
5464// objectsToDelete.Add(grp);
5465// return;
5466// }
5467// }
5468// });
5469// }
5470//
5471// foreach (SceneObjectGroup grp in objectsToDelete)
5472// {
5473// m_log.InfoFormat("[SCENE]: Deleting dropped attachment {0} of user {1}", grp.UUID, grp.OwnerID);
5474// DeleteSceneObject(grp, true);
5475// }
5476// }
5477
5478 public void ThreadAlive(int threadCode)
5479 {
5480 switch(threadCode)
5481 {
5482 case 1: // Incoming
5483 m_lastIncoming = Util.EnvironmentTickCount();
5484 break;
5485 case 2: // Incoming
5486 m_lastOutgoing = Util.EnvironmentTickCount();
5487 break;
5488 }
5489 }
5490
5491 public void RegenerateMaptileAndReregister(object sender, ElapsedEventArgs e)
5181 { 5492 {
5182 RegenerateMaptile(); 5493 RegenerateMaptile();
5183 5494
@@ -5205,6 +5516,8 @@ namespace OpenSim.Region.Framework.Scenes
5205 /// <returns></returns> 5516 /// <returns></returns>
5206 public bool QueryAccess(UUID agentID, Vector3 position, out string reason) 5517 public bool QueryAccess(UUID agentID, Vector3 position, out string reason)
5207 { 5518 {
5519 reason = "You are banned from the region";
5520
5208 if (EntityTransferModule.IsInTransit(agentID)) 5521 if (EntityTransferModule.IsInTransit(agentID))
5209 { 5522 {
5210 reason = "Agent is still in transit from this region"; 5523 reason = "Agent is still in transit from this region";
@@ -5216,6 +5529,12 @@ namespace OpenSim.Region.Framework.Scenes
5216 return false; 5529 return false;
5217 } 5530 }
5218 5531
5532 if (Permissions.IsGod(agentID))
5533 {
5534 reason = String.Empty;
5535 return true;
5536 }
5537
5219 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. 5538 // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check.
5220 // However, the long term fix is to make sure root agent count is always accurate. 5539 // However, the long term fix is to make sure root agent count is always accurate.
5221 m_sceneGraph.RecalculateStats(); 5540 m_sceneGraph.RecalculateStats();
@@ -5236,6 +5555,41 @@ namespace OpenSim.Region.Framework.Scenes
5236 } 5555 }
5237 } 5556 }
5238 5557
5558 ScenePresence presence = GetScenePresence(agentID);
5559 IClientAPI client = null;
5560 AgentCircuitData aCircuit = null;
5561
5562 if (presence != null)
5563 {
5564 client = presence.ControllingClient;
5565 if (client != null)
5566 aCircuit = client.RequestClientInfo();
5567 }
5568
5569 // We may be called before there is a presence or a client.
5570 // Fake AgentCircuitData to keep IAuthorizationModule smiling
5571 if (client == null)
5572 {
5573 aCircuit = new AgentCircuitData();
5574 aCircuit.AgentID = agentID;
5575 aCircuit.firstname = String.Empty;
5576 aCircuit.lastname = String.Empty;
5577 }
5578
5579 try
5580 {
5581 if (!AuthorizeUser(aCircuit, out reason))
5582 {
5583 // m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID);
5584 return false;
5585 }
5586 }
5587 catch (Exception e)
5588 {
5589 m_log.DebugFormat("[SCENE]: Exception authorizing agent: {0} "+ e.StackTrace, e.Message);
5590 return false;
5591 }
5592
5239 if (position == Vector3.Zero) // Teleport 5593 if (position == Vector3.Zero) // Teleport
5240 { 5594 {
5241 if (!RegionInfo.EstateSettings.AllowDirectTeleport) 5595 if (!RegionInfo.EstateSettings.AllowDirectTeleport)
@@ -5264,13 +5618,46 @@ namespace OpenSim.Region.Framework.Scenes
5264 } 5618 }
5265 } 5619 }
5266 } 5620 }
5621
5622 float posX = 128.0f;
5623 float posY = 128.0f;
5624
5625 if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY))
5626 {
5627 // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID);
5628 return false;
5629 }
5630 }
5631 else // Walking
5632 {
5633 ILandObject land = LandChannel.GetLandObject(position.X, position.Y);
5634 if (land == null)
5635 return false;
5636
5637 bool banned = land.IsBannedFromLand(agentID);
5638 bool restricted = land.IsRestrictedFromLand(agentID);
5639
5640 if (banned || restricted)
5641 return false;
5267 } 5642 }
5268 5643
5269 reason = String.Empty; 5644 reason = String.Empty;
5270 return true; 5645 return true;
5271 } 5646 }
5272 5647
5273 /// <summary> 5648 public void StartTimerWatchdog()
5649 {
5650 m_timerWatchdog.Interval = 1000;
5651 m_timerWatchdog.Elapsed += TimerWatchdog;
5652 m_timerWatchdog.AutoReset = true;
5653 m_timerWatchdog.Start();
5654 }
5655
5656 public void TimerWatchdog(object sender, ElapsedEventArgs e)
5657 {
5658 CheckHeartbeat();
5659 }
5660
5274 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the 5661 /// This method deals with movement when an avatar is automatically moving (but this is distinct from the
5275 /// autopilot that moves an avatar to a sit target!. 5662 /// autopilot that moves an avatar to a sit target!.
5276 /// </summary> 5663 /// </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 b8616e8..77e808e 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;
@@ -182,10 +182,13 @@ namespace OpenSim.Region.Framework.Scenes
182 } 182 }
183 } 183 }
184 184
185 public delegate void SendCloseChildAgentDelegate(UUID agentID, ulong regionHandle);
186
185 /// <summary> 187 /// <summary>
186 /// Closes a child agent on a given region 188 /// This Closes child agents on neighboring regions
189 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
187 /// </summary> 190 /// </summary>
188 protected void SendCloseChildAgent(UUID agentID, ulong regionHandle) 191 protected void SendCloseChildAgentAsync(UUID agentID, ulong regionHandle)
189 { 192 {
190 // let's do our best, but there's not much we can do if the neighbour doesn't accept. 193 // let's do our best, but there's not much we can do if the neighbour doesn't accept.
191 194
@@ -194,31 +197,29 @@ namespace OpenSim.Region.Framework.Scenes
194 Utils.LongToUInts(regionHandle, out x, out y); 197 Utils.LongToUInts(regionHandle, out x, out y);
195 198
196 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y); 199 GridRegion destination = m_scene.GridService.GetRegionByPosition(m_regionInfo.ScopeID, (int)x, (int)y);
200 m_scene.SimulationService.CloseChildAgent(destination, agentID);
201 }
197 202
198 m_log.DebugFormat( 203 private void SendCloseChildAgentCompleted(IAsyncResult iar)
199 "[INTERGRID]: Sending close agent {0} to region at {1}-{2}", 204 {
200 agentID, destination.RegionCoordX, destination.RegionCoordY); 205 SendCloseChildAgentDelegate icon = (SendCloseChildAgentDelegate)iar.AsyncState;
201 206 icon.EndInvoke(iar);
202 m_scene.SimulationService.CloseAgent(destination, agentID);
203 } 207 }
204 208
205 /// <summary>
206 /// Closes a child agents in a collection of regions. Does so asynchronously
207 /// so that the caller doesn't wait.
208 /// </summary>
209 /// <param name="agentID"></param>
210 /// <param name="regionslst"></param>
211 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst) 209 public void SendCloseChildAgentConnections(UUID agentID, List<ulong> regionslst)
212 { 210 {
213 foreach (ulong handle in regionslst) 211 foreach (ulong handle in regionslst)
214 { 212 {
215 SendCloseChildAgent(agentID, handle); 213 SendCloseChildAgentDelegate d = SendCloseChildAgentAsync;
214 d.BeginInvoke(agentID, handle,
215 SendCloseChildAgentCompleted,
216 d);
216 } 217 }
217 } 218 }
218 219
219 public List<GridRegion> RequestNamedRegions(string name, int maxNumber) 220 public List<GridRegion> RequestNamedRegions(string name, int maxNumber)
220 { 221 {
221 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber); 222 return m_scene.GridService.GetRegionsByName(UUID.Zero, name, maxNumber);
222 } 223 }
223 } 224 }
224} \ No newline at end of file 225}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index ddf1550..23a0550 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
@@ -127,13 +137,18 @@ namespace OpenSim.Region.Framework.Scenes
127 137
128 protected internal void Close() 138 protected internal void Close()
129 { 139 {
130 lock (m_presenceLock) 140 m_scenePresencesLock.EnterWriteLock();
141 try
131 { 142 {
132 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(); 143 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
133 List<ScenePresence> newlist = new List<ScenePresence>(); 144 List<ScenePresence> newlist = new List<ScenePresence>();
134 m_scenePresenceMap = newmap; 145 m_scenePresenceMap = newmap;
135 m_scenePresenceArray = newlist; 146 m_scenePresenceArray = newlist;
136 } 147 }
148 finally
149 {
150 m_scenePresencesLock.ExitWriteLock();
151 }
137 152
138 lock (SceneObjectGroupsByFullID) 153 lock (SceneObjectGroupsByFullID)
139 SceneObjectGroupsByFullID.Clear(); 154 SceneObjectGroupsByFullID.Clear();
@@ -254,6 +269,33 @@ namespace OpenSim.Region.Framework.Scenes
254 protected internal bool AddRestoredSceneObject( 269 protected internal bool AddRestoredSceneObject(
255 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) 270 SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates)
256 { 271 {
272 if (!m_parentScene.CombineRegions)
273 {
274 // KF: Check for out-of-region, move inside and make static.
275 Vector3 npos = new Vector3(sceneObject.RootPart.GroupPosition.X,
276 sceneObject.RootPart.GroupPosition.Y,
277 sceneObject.RootPart.GroupPosition.Z);
278 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 ||
279 npos.X > Constants.RegionSize ||
280 npos.Y > Constants.RegionSize))
281 {
282 if (npos.X < 0.0) npos.X = 1.0f;
283 if (npos.Y < 0.0) npos.Y = 1.0f;
284 if (npos.Z < 0.0) npos.Z = 0.0f;
285 if (npos.X > Constants.RegionSize) npos.X = Constants.RegionSize - 1.0f;
286 if (npos.Y > Constants.RegionSize) npos.Y = Constants.RegionSize - 1.0f;
287
288 foreach (SceneObjectPart part in sceneObject.Parts)
289 {
290 part.GroupPosition = npos;
291 }
292 sceneObject.RootPart.Velocity = Vector3.Zero;
293 sceneObject.RootPart.AngularVelocity = Vector3.Zero;
294 sceneObject.RootPart.Acceleration = Vector3.Zero;
295 sceneObject.RootPart.Velocity = Vector3.Zero;
296 }
297 }
298
257 if (attachToBackup && (!alreadyPersisted)) 299 if (attachToBackup && (!alreadyPersisted))
258 { 300 {
259 sceneObject.ForceInventoryPersistence(); 301 sceneObject.ForceInventoryPersistence();
@@ -319,7 +361,7 @@ namespace OpenSim.Region.Framework.Scenes
319 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false); 361 sceneObject.RootPart.ApplyImpulse((vel * sceneObject.GetMass()), false);
320 sceneObject.Velocity = vel; 362 sceneObject.Velocity = vel;
321 } 363 }
322 364
323 return true; 365 return true;
324 } 366 }
325 367
@@ -344,6 +386,11 @@ namespace OpenSim.Region.Framework.Scenes
344 /// </returns> 386 /// </returns>
345 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 387 protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
346 { 388 {
389 if (sceneObject == null)
390 {
391 m_log.ErrorFormat("[SCENEGRAPH]: Tried to add null scene object");
392 return false;
393 }
347 if (sceneObject.UUID == UUID.Zero) 394 if (sceneObject.UUID == UUID.Zero)
348 { 395 {
349 m_log.ErrorFormat( 396 m_log.ErrorFormat(
@@ -478,6 +525,30 @@ namespace OpenSim.Region.Framework.Scenes
478 m_updateList[obj.UUID] = obj; 525 m_updateList[obj.UUID] = obj;
479 } 526 }
480 527
528 public void FireAttachToBackup(SceneObjectGroup obj)
529 {
530 if (OnAttachToBackup != null)
531 {
532 OnAttachToBackup(obj);
533 }
534 }
535
536 public void FireDetachFromBackup(SceneObjectGroup obj)
537 {
538 if (OnDetachFromBackup != null)
539 {
540 OnDetachFromBackup(obj);
541 }
542 }
543
544 public void FireChangeBackup(SceneObjectGroup obj)
545 {
546 if (OnChangeBackup != null)
547 {
548 OnChangeBackup(obj);
549 }
550 }
551
481 /// <summary> 552 /// <summary>
482 /// Process all pending updates 553 /// Process all pending updates
483 /// </summary> 554 /// </summary>
@@ -595,7 +666,8 @@ namespace OpenSim.Region.Framework.Scenes
595 666
596 Entities[presence.UUID] = presence; 667 Entities[presence.UUID] = presence;
597 668
598 lock (m_presenceLock) 669 m_scenePresencesLock.EnterWriteLock();
670 try
599 { 671 {
600 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 672 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
601 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 673 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -619,6 +691,10 @@ namespace OpenSim.Region.Framework.Scenes
619 m_scenePresenceMap = newmap; 691 m_scenePresenceMap = newmap;
620 m_scenePresenceArray = newlist; 692 m_scenePresenceArray = newlist;
621 } 693 }
694 finally
695 {
696 m_scenePresencesLock.ExitWriteLock();
697 }
622 } 698 }
623 699
624 /// <summary> 700 /// <summary>
@@ -633,7 +709,8 @@ namespace OpenSim.Region.Framework.Scenes
633 agentID); 709 agentID);
634 } 710 }
635 711
636 lock (m_presenceLock) 712 m_scenePresencesLock.EnterWriteLock();
713 try
637 { 714 {
638 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap); 715 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
639 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray); 716 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
@@ -655,6 +732,10 @@ namespace OpenSim.Region.Framework.Scenes
655 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 732 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
656 } 733 }
657 } 734 }
735 finally
736 {
737 m_scenePresencesLock.ExitWriteLock();
738 }
658 } 739 }
659 740
660 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F) 741 protected internal void SwapRootChildAgent(bool direction_RC_CR_T_F)
@@ -1182,6 +1263,52 @@ namespace OpenSim.Region.Framework.Scenes
1182 1263
1183 #region Client Event handlers 1264 #region Client Event handlers
1184 1265
1266 protected internal void ClientChangeObject(uint localID, object odata, IClientAPI remoteClient)
1267 {
1268 SceneObjectPart part = GetSceneObjectPart(localID);
1269 ObjectChangeData data = (ObjectChangeData)odata;
1270
1271 if (part != null)
1272 {
1273 SceneObjectGroup grp = part.ParentGroup;
1274 if (grp != null)
1275 {
1276 if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId))
1277 {
1278 // These two are exceptions SL makes in the interpretation
1279 // of the change flags. Must check them here because otherwise
1280 // the group flag (see below) would be lost
1281 if (data.change == ObjectChangeType.groupS)
1282 data.change = ObjectChangeType.primS;
1283 if (data.change == ObjectChangeType.groupPS)
1284 data.change = ObjectChangeType.primPS;
1285 part.StoreUndoState(data.change); // lets test only saving what we changed
1286 grp.doChangeObject(part, (ObjectChangeData)data);
1287 }
1288 else
1289 {
1290 // Is this any kind of group operation?
1291 if ((data.change & ObjectChangeType.Group) != 0)
1292 {
1293 // Is a move and/or rotation requested?
1294 if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0)
1295 {
1296 // Are we allowed to move it?
1297 if (m_parentScene.Permissions.CanMoveObject(grp.UUID, remoteClient.AgentId))
1298 {
1299 // Strip all but move and rotation from request
1300 data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation);
1301
1302 part.StoreUndoState(data.change);
1303 grp.doChangeObject(part, (ObjectChangeData)data);
1304 }
1305 }
1306 }
1307 }
1308 }
1309 }
1310 }
1311
1185 /// <summary> 1312 /// <summary>
1186 /// Update the scale of an individual prim. 1313 /// Update the scale of an individual prim.
1187 /// </summary> 1314 /// </summary>
@@ -1196,7 +1323,17 @@ namespace OpenSim.Region.Framework.Scenes
1196 { 1323 {
1197 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) 1324 if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId))
1198 { 1325 {
1326 bool physbuild = false;
1327 if (part.ParentGroup.RootPart.PhysActor != null)
1328 {
1329 part.ParentGroup.RootPart.PhysActor.Building = true;
1330 physbuild = true;
1331 }
1332
1199 part.Resize(scale); 1333 part.Resize(scale);
1334
1335 if (physbuild)
1336 part.ParentGroup.RootPart.PhysActor.Building = false;
1200 } 1337 }
1201 } 1338 }
1202 } 1339 }
@@ -1208,7 +1345,17 @@ namespace OpenSim.Region.Framework.Scenes
1208 { 1345 {
1209 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1346 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1210 { 1347 {
1348 bool physbuild = false;
1349 if (group.RootPart.PhysActor != null)
1350 {
1351 group.RootPart.PhysActor.Building = true;
1352 physbuild = true;
1353 }
1354
1211 group.GroupResize(scale); 1355 group.GroupResize(scale);
1356
1357 if (physbuild)
1358 group.RootPart.PhysActor.Building = false;
1212 } 1359 }
1213 } 1360 }
1214 } 1361 }
@@ -1336,8 +1483,13 @@ namespace OpenSim.Region.Framework.Scenes
1336 { 1483 {
1337 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) 1484 if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0))
1338 { 1485 {
1339 if (m_parentScene.AttachmentsModule != null) 1486 // Set the new attachment point data in the object
1340 m_parentScene.AttachmentsModule.UpdateAttachmentPosition(group, pos); 1487 byte attachmentPoint = group.GetAttachmentPoint();
1488 group.UpdateGroupPosition(pos);
1489 group.IsAttachment = false;
1490 group.AbsolutePosition = group.RootPart.AttachedPos;
1491 group.AttachmentPoint = attachmentPoint;
1492 group.HasGroupChanged = true;
1341 } 1493 }
1342 else 1494 else
1343 { 1495 {
@@ -1385,7 +1537,7 @@ namespace OpenSim.Region.Framework.Scenes
1385 /// <param name="SetPhantom"></param> 1537 /// <param name="SetPhantom"></param>
1386 /// <param name="remoteClient"></param> 1538 /// <param name="remoteClient"></param>
1387 protected internal void UpdatePrimFlags( 1539 protected internal void UpdatePrimFlags(
1388 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, IClientAPI remoteClient) 1540 uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, ExtraPhysicsData PhysData, IClientAPI remoteClient)
1389 { 1541 {
1390 SceneObjectGroup group = GetGroupByPrim(localID); 1542 SceneObjectGroup group = GetGroupByPrim(localID);
1391 if (group != null) 1543 if (group != null)
@@ -1393,7 +1545,28 @@ namespace OpenSim.Region.Framework.Scenes
1393 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) 1545 if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId))
1394 { 1546 {
1395 // VolumeDetect can't be set via UI and will always be off when a change is made there 1547 // VolumeDetect can't be set via UI and will always be off when a change is made there
1396 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, false); 1548 // now only change volume dtc if phantom off
1549
1550 if (PhysData.PhysShapeType == PhysShapeType.invalid) // check for extraPhysics data
1551 {
1552 bool vdtc;
1553 if (SetPhantom) // if phantom keep volumedtc
1554 vdtc = group.RootPart.VolumeDetectActive;
1555 else // else turn it off
1556 vdtc = false;
1557
1558 group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc);
1559 }
1560 else
1561 {
1562 SceneObjectPart part = GetSceneObjectPart(localID);
1563 if (part != null)
1564 {
1565 part.UpdateExtraPhysics(PhysData);
1566 if (part.UpdatePhysRequired)
1567 remoteClient.SendPartPhysicsProprieties(part);
1568 }
1569 }
1397 } 1570 }
1398 } 1571 }
1399 } 1572 }
@@ -1537,6 +1710,7 @@ namespace OpenSim.Region.Framework.Scenes
1537 { 1710 {
1538 part.Material = Convert.ToByte(material); 1711 part.Material = Convert.ToByte(material);
1539 group.HasGroupChanged = true; 1712 group.HasGroupChanged = true;
1713 remoteClient.SendPartPhysicsProprieties(part);
1540 } 1714 }
1541 } 1715 }
1542 } 1716 }
@@ -1601,6 +1775,12 @@ namespace OpenSim.Region.Framework.Scenes
1601 /// <param name="childPrims"></param> 1775 /// <param name="childPrims"></param>
1602 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children) 1776 protected internal void LinkObjects(SceneObjectPart root, List<SceneObjectPart> children)
1603 { 1777 {
1778 if (root.KeyframeMotion != null)
1779 {
1780 root.KeyframeMotion.Stop();
1781 root.KeyframeMotion = null;
1782 }
1783
1604 SceneObjectGroup parentGroup = root.ParentGroup; 1784 SceneObjectGroup parentGroup = root.ParentGroup;
1605 if (parentGroup == null) return; 1785 if (parentGroup == null) return;
1606 1786
@@ -1609,8 +1789,11 @@ namespace OpenSim.Region.Framework.Scenes
1609 return; 1789 return;
1610 1790
1611 Monitor.Enter(m_updateLock); 1791 Monitor.Enter(m_updateLock);
1792
1612 try 1793 try
1613 { 1794 {
1795 parentGroup.areUpdatesSuspended = true;
1796
1614 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>(); 1797 List<SceneObjectGroup> childGroups = new List<SceneObjectGroup>();
1615 1798
1616 // We do this in reverse to get the link order of the prims correct 1799 // We do this in reverse to get the link order of the prims correct
@@ -1625,9 +1808,13 @@ namespace OpenSim.Region.Framework.Scenes
1625 // Make sure no child prim is set for sale 1808 // Make sure no child prim is set for sale
1626 // So that, on delink, no prims are unwittingly 1809 // So that, on delink, no prims are unwittingly
1627 // left for sale and sold off 1810 // left for sale and sold off
1628 child.RootPart.ObjectSaleType = 0; 1811
1629 child.RootPart.SalePrice = 10; 1812 if (child != null)
1630 childGroups.Add(child); 1813 {
1814 child.RootPart.ObjectSaleType = 0;
1815 child.RootPart.SalePrice = 10;
1816 childGroups.Add(child);
1817 }
1631 } 1818 }
1632 1819
1633 foreach (SceneObjectGroup child in childGroups) 1820 foreach (SceneObjectGroup child in childGroups)
@@ -1654,6 +1841,16 @@ namespace OpenSim.Region.Framework.Scenes
1654 } 1841 }
1655 finally 1842 finally
1656 { 1843 {
1844 lock (SceneObjectGroupsByLocalPartID)
1845 {
1846 foreach (SceneObjectPart part in parentGroup.Parts)
1847 SceneObjectGroupsByLocalPartID[part.LocalId] = parentGroup;
1848 }
1849
1850 parentGroup.areUpdatesSuspended = false;
1851 parentGroup.HasGroupChanged = true;
1852 parentGroup.ProcessBackup(m_parentScene.SimulationDataService, true);
1853 parentGroup.ScheduleGroupForFullUpdate();
1657 Monitor.Exit(m_updateLock); 1854 Monitor.Exit(m_updateLock);
1658 } 1855 }
1659 } 1856 }
@@ -1676,6 +1873,11 @@ namespace OpenSim.Region.Framework.Scenes
1676 { 1873 {
1677 if (part != null) 1874 if (part != null)
1678 { 1875 {
1876 if (part.KeyframeMotion != null)
1877 {
1878 part.KeyframeMotion.Stop();
1879 part.KeyframeMotion = null;
1880 }
1679 if (part.ParentGroup.PrimCount != 1) // Skip single 1881 if (part.ParentGroup.PrimCount != 1) // Skip single
1680 { 1882 {
1681 if (part.LinkNum < 2) // Root 1883 if (part.LinkNum < 2) // Root
@@ -1690,21 +1892,24 @@ namespace OpenSim.Region.Framework.Scenes
1690 1892
1691 SceneObjectGroup group = part.ParentGroup; 1893 SceneObjectGroup group = part.ParentGroup;
1692 if (!affectedGroups.Contains(group)) 1894 if (!affectedGroups.Contains(group))
1895 {
1896 group.areUpdatesSuspended = true;
1693 affectedGroups.Add(group); 1897 affectedGroups.Add(group);
1898 }
1694 } 1899 }
1695 } 1900 }
1696 } 1901 }
1697 1902
1698 foreach (SceneObjectPart child in childParts) 1903 if (childParts.Count > 0)
1699 { 1904 {
1700 // Unlink all child parts from their groups 1905 foreach (SceneObjectPart child in childParts)
1701 // 1906 {
1702 child.ParentGroup.DelinkFromGroup(child, true); 1907 // Unlink all child parts from their groups
1703 1908 //
1704 // These are not in affected groups and will not be 1909 child.ParentGroup.DelinkFromGroup(child, true);
1705 // handled further. Do the honors here. 1910 child.ParentGroup.HasGroupChanged = true;
1706 child.ParentGroup.HasGroupChanged = true; 1911 child.ParentGroup.ScheduleGroupForFullUpdate();
1707 child.ParentGroup.ScheduleGroupForFullUpdate(); 1912 }
1708 } 1913 }
1709 1914
1710 foreach (SceneObjectPart root in rootParts) 1915 foreach (SceneObjectPart root in rootParts)
@@ -1714,56 +1919,68 @@ namespace OpenSim.Region.Framework.Scenes
1714 // However, editing linked parts and unlinking may be different 1919 // However, editing linked parts and unlinking may be different
1715 // 1920 //
1716 SceneObjectGroup group = root.ParentGroup; 1921 SceneObjectGroup group = root.ParentGroup;
1922 group.areUpdatesSuspended = true;
1717 1923
1718 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts); 1924 List<SceneObjectPart> newSet = new List<SceneObjectPart>(group.Parts);
1719 int numChildren = newSet.Count; 1925 int numChildren = newSet.Count;
1720 1926
1927 if (numChildren == 1)
1928 break;
1929
1721 // If there are prims left in a link set, but the root is 1930 // If there are prims left in a link set, but the root is
1722 // slated for unlink, we need to do this 1931 // slated for unlink, we need to do this
1932 // Unlink the remaining set
1723 // 1933 //
1724 if (numChildren != 1) 1934 bool sendEventsToRemainder = true;
1725 { 1935 if (numChildren > 1)
1726 // Unlink the remaining set 1936 sendEventsToRemainder = false;
1727 //
1728 bool sendEventsToRemainder = true;
1729 if (numChildren > 1)
1730 sendEventsToRemainder = false;
1731 1937
1732 foreach (SceneObjectPart p in newSet) 1938 foreach (SceneObjectPart p in newSet)
1939 {
1940 if (p != group.RootPart)
1733 { 1941 {
1734 if (p != group.RootPart) 1942 group.DelinkFromGroup(p, sendEventsToRemainder);
1735 group.DelinkFromGroup(p, sendEventsToRemainder); 1943 if (numChildren > 2)
1944 {
1945 p.ParentGroup.areUpdatesSuspended = true;
1946 }
1947 else
1948 {
1949 p.ParentGroup.HasGroupChanged = true;
1950 p.ParentGroup.ScheduleGroupForFullUpdate();
1951 }
1736 } 1952 }
1953 }
1954
1955 // If there is more than one prim remaining, we
1956 // need to re-link
1957 //
1958 if (numChildren > 2)
1959 {
1960 // Remove old root
1961 //
1962 if (newSet.Contains(root))
1963 newSet.Remove(root);
1737 1964
1738 // If there is more than one prim remaining, we 1965 // Preserve link ordering
1739 // need to re-link
1740 // 1966 //
1741 if (numChildren > 2) 1967 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1742 { 1968 {
1743 // Remove old root 1969 return a.LinkNum.CompareTo(b.LinkNum);
1744 // 1970 });
1745 if (newSet.Contains(root))
1746 newSet.Remove(root);
1747
1748 // Preserve link ordering
1749 //
1750 newSet.Sort(delegate (SceneObjectPart a, SceneObjectPart b)
1751 {
1752 return a.LinkNum.CompareTo(b.LinkNum);
1753 });
1754 1971
1755 // Determine new root 1972 // Determine new root
1756 // 1973 //
1757 SceneObjectPart newRoot = newSet[0]; 1974 SceneObjectPart newRoot = newSet[0];
1758 newSet.RemoveAt(0); 1975 newSet.RemoveAt(0);
1759 1976
1760 foreach (SceneObjectPart newChild in newSet) 1977 foreach (SceneObjectPart newChild in newSet)
1761 newChild.ClearUpdateSchedule(); 1978 newChild.ClearUpdateSchedule();
1762 1979
1763 LinkObjects(newRoot, newSet); 1980 newRoot.ParentGroup.areUpdatesSuspended = true;
1764 if (!affectedGroups.Contains(newRoot.ParentGroup)) 1981 LinkObjects(newRoot, newSet);
1765 affectedGroups.Add(newRoot.ParentGroup); 1982 if (!affectedGroups.Contains(newRoot.ParentGroup))
1766 } 1983 affectedGroups.Add(newRoot.ParentGroup);
1767 } 1984 }
1768 } 1985 }
1769 1986
@@ -1771,8 +1988,14 @@ namespace OpenSim.Region.Framework.Scenes
1771 // 1988 //
1772 foreach (SceneObjectGroup g in affectedGroups) 1989 foreach (SceneObjectGroup g in affectedGroups)
1773 { 1990 {
1991 // Child prims that have been unlinked and deleted will
1992 // return unless the root is deleted. This will remove them
1993 // from the database. They will be rewritten immediately,
1994 // minus the rows for the unlinked child prims.
1995 m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID);
1774 g.TriggerScriptChangedEvent(Changed.LINK); 1996 g.TriggerScriptChangedEvent(Changed.LINK);
1775 g.HasGroupChanged = true; // Persist 1997 g.HasGroupChanged = true; // Persist
1998 g.areUpdatesSuspended = false;
1776 g.ScheduleGroupForFullUpdate(); 1999 g.ScheduleGroupForFullUpdate();
1777 } 2000 }
1778 } 2001 }
@@ -1844,108 +2067,96 @@ namespace OpenSim.Region.Framework.Scenes
1844 /// <param name="GroupID"></param> 2067 /// <param name="GroupID"></param>
1845 /// <param name="rot"></param> 2068 /// <param name="rot"></param>
1846 /// <returns>null if duplication fails, otherwise the duplicated object</returns> 2069 /// <returns>null if duplication fails, otherwise the duplicated object</returns>
1847 public SceneObjectGroup DuplicateObject( 2070 /// <summary>
1848 uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 2071 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1849 { 2072 {
1850 Monitor.Enter(m_updateLock); 2073// m_log.DebugFormat(
2074// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
2075// originalPrimID, offset, AgentID);
1851 2076
1852 try 2077 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
2078 if (original != null)
1853 { 2079 {
1854 // m_log.DebugFormat( 2080 if (m_parentScene.Permissions.CanDuplicateObject(
1855 // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", 2081 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1856 // originalPrimID, offset, AgentID);
1857
1858 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1859 if (original == null)
1860 { 2082 {
1861 m_log.WarnFormat( 2083 SceneObjectGroup copy = original.Copy(true);
1862 "[SCENEGRAPH]: Attempt to duplicate nonexistant prim id {0} by {1}", originalPrimID, AgentID); 2084 copy.AbsolutePosition = copy.AbsolutePosition + offset;
1863 2085
1864 return null; 2086 if (original.OwnerID != AgentID)
1865 } 2087 {
2088 copy.SetOwnerId(AgentID);
2089 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1866 2090
1867 if (!m_parentScene.Permissions.CanDuplicateObject( 2091 SceneObjectPart[] partList = copy.Parts;
1868 original.PrimCount, original.UUID, AgentID, original.AbsolutePosition))
1869 return null;
1870 2092
1871 SceneObjectGroup copy = original.Copy(true); 2093 if (m_parentScene.Permissions.PropagatePermissions())
1872 copy.AbsolutePosition = copy.AbsolutePosition + offset; 2094 {
2095 foreach (SceneObjectPart child in partList)
2096 {
2097 child.Inventory.ChangeInventoryOwner(AgentID);
2098 child.TriggerScriptChangedEvent(Changed.OWNER);
2099 child.ApplyNextOwnerPermissions();
2100 }
2101 }
2102 }
1873 2103
1874 if (original.OwnerID != AgentID) 2104 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1875 { 2105 Entities.Add(copy);
1876 copy.SetOwnerId(AgentID);
1877 copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID);
1878 2106
1879 SceneObjectPart[] partList = copy.Parts; 2107 lock (SceneObjectGroupsByFullID)
2108 SceneObjectGroupsByFullID[copy.UUID] = copy;
1880 2109
1881 if (m_parentScene.Permissions.PropagatePermissions()) 2110 SceneObjectPart[] children = copy.Parts;
2111
2112 lock (SceneObjectGroupsByFullPartID)
1882 { 2113 {
1883 foreach (SceneObjectPart child in partList) 2114 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1884 { 2115 foreach (SceneObjectPart part in children)
1885 child.Inventory.ChangeInventoryOwner(AgentID); 2116 SceneObjectGroupsByFullPartID[part.UUID] = copy;
1886 child.TriggerScriptChangedEvent(Changed.OWNER);
1887 child.ApplyNextOwnerPermissions();
1888 }
1889 } 2117 }
1890 2118
1891 copy.RootPart.ObjectSaleType = 0; 2119 lock (SceneObjectGroupsByLocalPartID)
1892 copy.RootPart.SalePrice = 10; 2120 {
1893 } 2121 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
2122 foreach (SceneObjectPart part in children)
2123 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
2124 }
2125 // PROBABLE END OF FIXME
1894 2126
1895 // FIXME: This section needs to be refactored so that it just calls AddSceneObject() 2127 // Since we copy from a source group that is in selected
1896 Entities.Add(copy); 2128 // state, but the copy is shown deselected in the viewer,
1897 2129 // We need to clear the selection flag here, else that
1898 lock (SceneObjectGroupsByFullID) 2130 // prim never gets persisted at all. The client doesn't
1899 SceneObjectGroupsByFullID[copy.UUID] = copy; 2131 // think it's selected, so it will never send a deselect...
1900 2132 copy.IsSelected = false;
1901 SceneObjectPart[] children = copy.Parts; 2133
1902 2134 m_numPrim += copy.Parts.Length;
1903 lock (SceneObjectGroupsByFullPartID) 2135
1904 { 2136 if (rot != Quaternion.Identity)
1905 SceneObjectGroupsByFullPartID[copy.UUID] = copy; 2137 {
1906 foreach (SceneObjectPart part in children) 2138 copy.UpdateGroupRotationR(rot);
1907 SceneObjectGroupsByFullPartID[part.UUID] = copy; 2139 }
1908 }
1909
1910 lock (SceneObjectGroupsByLocalPartID)
1911 {
1912 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1913 foreach (SceneObjectPart part in children)
1914 SceneObjectGroupsByLocalPartID[part.LocalId] = copy;
1915 }
1916 // PROBABLE END OF FIXME
1917
1918 // Since we copy from a source group that is in selected
1919 // state, but the copy is shown deselected in the viewer,
1920 // We need to clear the selection flag here, else that
1921 // prim never gets persisted at all. The client doesn't
1922 // think it's selected, so it will never send a deselect...
1923 copy.IsSelected = false;
1924
1925 m_numPrim += copy.Parts.Length;
1926
1927 if (rot != Quaternion.Identity)
1928 {
1929 copy.UpdateGroupRotationR(rot);
1930 }
1931 2140
1932 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); 2141 copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1);
1933 copy.HasGroupChanged = true; 2142 copy.HasGroupChanged = true;
1934 copy.ScheduleGroupForFullUpdate(); 2143 copy.ScheduleGroupForFullUpdate();
1935 copy.ResumeScripts(); 2144 copy.ResumeScripts();
1936 2145
1937 // required for physics to update it's position 2146 // required for physics to update it's position
1938 copy.AbsolutePosition = copy.AbsolutePosition; 2147 copy.AbsolutePosition = copy.AbsolutePosition;
1939 2148
1940 return copy; 2149 return copy;
2150 }
1941 } 2151 }
1942 finally 2152 else
1943 { 2153 {
1944 Monitor.Exit(m_updateLock); 2154 m_log.WarnFormat("[SCENE]: Attempted to duplicate nonexistant prim id {0}", GroupID);
1945 } 2155 }
2156
2157 return null;
1946 } 2158 }
1947 2159
1948 /// <summary>
1949 /// Calculates the distance between two Vector3s 2160 /// Calculates the distance between two Vector3s
1950 /// </summary> 2161 /// </summary>
1951 /// <param name="v1"></param> 2162 /// <param name="v1"></param>
diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs
index d73a959..e3fed49 100644
--- a/OpenSim/Region/Framework/Scenes/SceneManager.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs
@@ -53,12 +53,12 @@ namespace OpenSim.Region.Framework.Scenes
53 get { return m_instance; } 53 get { return m_instance; }
54 } 54 }
55 55
56 private readonly List<Scene> m_localScenes = new List<Scene>(); 56 private readonly DoubleDictionary<UUID, string, Scene> m_localScenes = new DoubleDictionary<UUID, string, Scene>();
57 private Scene m_currentScene = null; 57 private Scene m_currentScene = null;
58 58
59 public List<Scene> Scenes 59 public List<Scene> Scenes
60 { 60 {
61 get { return new List<Scene>(m_localScenes); } 61 get { return new List<Scene>(m_localScenes.FindAll(delegate(Scene s) { return true; })); }
62 } 62 }
63 63
64 public Scene CurrentScene 64 public Scene CurrentScene
@@ -72,13 +72,10 @@ namespace OpenSim.Region.Framework.Scenes
72 { 72 {
73 if (m_currentScene == null) 73 if (m_currentScene == null)
74 { 74 {
75 lock (m_localScenes) 75 List<Scene> sceneList = Scenes;
76 { 76 if (sceneList.Count == 0)
77 if (m_localScenes.Count > 0) 77 return null;
78 return m_localScenes[0]; 78 return sceneList[0];
79 else
80 return null;
81 }
82 } 79 }
83 else 80 else
84 { 81 {
@@ -90,7 +87,7 @@ namespace OpenSim.Region.Framework.Scenes
90 public SceneManager() 87 public SceneManager()
91 { 88 {
92 m_instance = this; 89 m_instance = this;
93 m_localScenes = new List<Scene>(); 90 m_localScenes = new DoubleDictionary<UUID, string, Scene>();
94 } 91 }
95 92
96 public void Close() 93 public void Close()
@@ -98,20 +95,18 @@ namespace OpenSim.Region.Framework.Scenes
98 // collect known shared modules in sharedModules 95 // collect known shared modules in sharedModules
99 Dictionary<string, IRegionModule> sharedModules = new Dictionary<string, IRegionModule>(); 96 Dictionary<string, IRegionModule> sharedModules = new Dictionary<string, IRegionModule>();
100 97
101 lock (m_localScenes) 98 List<Scene> sceneList = Scenes;
99 for (int i = 0; i < sceneList.Count; i++)
102 { 100 {
103 for (int i = 0; i < m_localScenes.Count; i++) 101 // extract known shared modules from scene
102 foreach (string k in sceneList[i].Modules.Keys)
104 { 103 {
105 // extract known shared modules from scene 104 if (sceneList[i].Modules[k].IsSharedModule &&
106 foreach (string k in m_localScenes[i].Modules.Keys) 105 !sharedModules.ContainsKey(k))
107 { 106 sharedModules[k] = sceneList[i].Modules[k];
108 if (m_localScenes[i].Modules[k].IsSharedModule &&
109 !sharedModules.ContainsKey(k))
110 sharedModules[k] = m_localScenes[i].Modules[k];
111 }
112 // close scene/region
113 m_localScenes[i].Close();
114 } 107 }
108 // close scene/region
109 sceneList[i].Close();
115 } 110 }
116 111
117 // all regions/scenes are now closed, we can now safely 112 // all regions/scenes are now closed, we can now safely
@@ -120,31 +115,22 @@ namespace OpenSim.Region.Framework.Scenes
120 { 115 {
121 mod.Close(); 116 mod.Close();
122 } 117 }
118
119 m_localScenes.Clear();
123 } 120 }
124 121
125 public void Close(Scene cscene) 122 public void Close(Scene cscene)
126 { 123 {
127 lock (m_localScenes) 124 if (!m_localScenes.ContainsKey(cscene.RegionInfo.RegionID))
128 { 125 return;
129 if (m_localScenes.Contains(cscene)) 126 cscene.Close();
130 {
131 for (int i = 0; i < m_localScenes.Count; i++)
132 {
133 if (m_localScenes[i].Equals(cscene))
134 {
135 m_localScenes[i].Close();
136 }
137 }
138 }
139 }
140 } 127 }
141 128
142 public void Add(Scene scene) 129 public void Add(Scene scene)
143 { 130 {
144 scene.OnRestart += HandleRestart; 131 scene.OnRestart += HandleRestart;
145 132
146 lock (m_localScenes) 133 m_localScenes.Add(scene.RegionInfo.RegionID, scene.RegionInfo.RegionName, scene);
147 m_localScenes.Add(scene);
148 } 134 }
149 135
150 public void HandleRestart(RegionInfo rdata) 136 public void HandleRestart(RegionInfo rdata)
@@ -152,24 +138,7 @@ namespace OpenSim.Region.Framework.Scenes
152 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main"); 138 m_log.Error("[SCENEMANAGER]: Got Restart message for region:" + rdata.RegionName + " Sending up to main");
153 int RegionSceneElement = -1; 139 int RegionSceneElement = -1;
154 140
155 lock (m_localScenes) 141 m_localScenes.Remove(rdata.RegionID);
156 {
157 for (int i = 0; i < m_localScenes.Count; i++)
158 {
159 if (rdata.RegionName == m_localScenes[i].RegionInfo.RegionName)
160 {
161 RegionSceneElement = i;
162 }
163 }
164
165 // Now we make sure the region is no longer known about by the SceneManager
166 // Prevents duplicates.
167
168 if (RegionSceneElement >= 0)
169 {
170 m_localScenes.RemoveAt(RegionSceneElement);
171 }
172 }
173 142
174 // Send signal to main that we're restarting this sim. 143 // Send signal to main that we're restarting this sim.
175 OnRestartSim(rdata); 144 OnRestartSim(rdata);
@@ -179,32 +148,29 @@ namespace OpenSim.Region.Framework.Scenes
179 { 148 {
180 RegionInfo Result = null; 149 RegionInfo Result = null;
181 150
182 lock (m_localScenes) 151 Scene s = m_localScenes.FindValue(delegate(Scene x)
183 {
184 for (int i = 0; i < m_localScenes.Count; i++)
185 {
186 if (m_localScenes[i].RegionInfo.RegionHandle == regionHandle)
187 { 152 {
188 // Inform other regions to tell their avatar about me 153 if (x.RegionInfo.RegionHandle == regionHandle)
189 Result = m_localScenes[i].RegionInfo; 154 return true;
190 } 155 return false;
191 } 156 });
192 157
193 if (Result != null) 158 if (s != null)
159 {
160 List<Scene> sceneList = Scenes;
161
162 for (int i = 0; i < sceneList.Count; i++)
194 { 163 {
195 for (int i = 0; i < m_localScenes.Count; i++) 164 if (sceneList[i]!= s)
196 { 165 {
197 if (m_localScenes[i].RegionInfo.RegionHandle != regionHandle) 166 // Inform other regions to tell their avatar about me
198 { 167 //sceneList[i].OtherRegionUp(Result);
199 // Inform other regions to tell their avatar about me
200 //m_localScenes[i].OtherRegionUp(Result);
201 }
202 } 168 }
203 } 169 }
204 else 170 }
205 { 171 else
206 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up"); 172 {
207 } 173 m_log.Error("[REGION]: Unable to notify Other regions of this Region coming up");
208 } 174 }
209 } 175 }
210 176
@@ -308,8 +274,8 @@ namespace OpenSim.Region.Framework.Scenes
308 { 274 {
309 if (m_currentScene == null) 275 if (m_currentScene == null)
310 { 276 {
311 lock (m_localScenes) 277 List<Scene> sceneList = Scenes;
312 m_localScenes.ForEach(func); 278 sceneList.ForEach(func);
313 } 279 }
314 else 280 else
315 { 281 {
@@ -338,16 +304,12 @@ namespace OpenSim.Region.Framework.Scenes
338 } 304 }
339 else 305 else
340 { 306 {
341 lock (m_localScenes) 307 Scene s;
308
309 if (m_localScenes.TryGetValue(regionName, out s))
342 { 310 {
343 foreach (Scene scene in m_localScenes) 311 m_currentScene = s;
344 { 312 return true;
345 if (String.Compare(scene.RegionInfo.RegionName, regionName, true) == 0)
346 {
347 m_currentScene = scene;
348 return true;
349 }
350 }
351 } 313 }
352 314
353 return false; 315 return false;
@@ -356,18 +318,14 @@ namespace OpenSim.Region.Framework.Scenes
356 318
357 public bool TrySetCurrentScene(UUID regionID) 319 public bool TrySetCurrentScene(UUID regionID)
358 { 320 {
359 m_log.Debug("Searching for Region: '" + regionID + "'"); 321// m_log.Debug("Searching for Region: '" + regionID + "'");
360 322
361 lock (m_localScenes) 323 Scene s;
324
325 if (m_localScenes.TryGetValue(regionID, out s))
362 { 326 {
363 foreach (Scene scene in m_localScenes) 327 m_currentScene = s;
364 { 328 return true;
365 if (scene.RegionInfo.RegionID == regionID)
366 {
367 m_currentScene = scene;
368 return true;
369 }
370 }
371 } 329 }
372 330
373 return false; 331 return false;
@@ -375,52 +333,24 @@ namespace OpenSim.Region.Framework.Scenes
375 333
376 public bool TryGetScene(string regionName, out Scene scene) 334 public bool TryGetScene(string regionName, out Scene scene)
377 { 335 {
378 lock (m_localScenes) 336 return m_localScenes.TryGetValue(regionName, out scene);
379 {
380 foreach (Scene mscene in m_localScenes)
381 {
382 if (String.Compare(mscene.RegionInfo.RegionName, regionName, true) == 0)
383 {
384 scene = mscene;
385 return true;
386 }
387 }
388 }
389
390 scene = null;
391 return false;
392 } 337 }
393 338
394 public bool TryGetScene(UUID regionID, out Scene scene) 339 public bool TryGetScene(UUID regionID, out Scene scene)
395 { 340 {
396 lock (m_localScenes) 341 return m_localScenes.TryGetValue(regionID, out scene);
397 {
398 foreach (Scene mscene in m_localScenes)
399 {
400 if (mscene.RegionInfo.RegionID == regionID)
401 {
402 scene = mscene;
403 return true;
404 }
405 }
406 }
407
408 scene = null;
409 return false;
410 } 342 }
411 343
412 public bool TryGetScene(uint locX, uint locY, out Scene scene) 344 public bool TryGetScene(uint locX, uint locY, out Scene scene)
413 { 345 {
414 lock (m_localScenes) 346 List<Scene> sceneList = Scenes;
347 foreach (Scene mscene in sceneList)
415 { 348 {
416 foreach (Scene mscene in m_localScenes) 349 if (mscene.RegionInfo.RegionLocX == locX &&
350 mscene.RegionInfo.RegionLocY == locY)
417 { 351 {
418 if (mscene.RegionInfo.RegionLocX == locX && 352 scene = mscene;
419 mscene.RegionInfo.RegionLocY == locY) 353 return true;
420 {
421 scene = mscene;
422 return true;
423 }
424 } 354 }
425 } 355 }
426 356
@@ -430,16 +360,14 @@ namespace OpenSim.Region.Framework.Scenes
430 360
431 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene) 361 public bool TryGetScene(IPEndPoint ipEndPoint, out Scene scene)
432 { 362 {
433 lock (m_localScenes) 363 List<Scene> sceneList = Scenes;
364 foreach (Scene mscene in sceneList)
434 { 365 {
435 foreach (Scene mscene in m_localScenes) 366 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) &&
367 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port))
436 { 368 {
437 if ((mscene.RegionInfo.InternalEndPoint.Equals(ipEndPoint.Address)) && 369 scene = mscene;
438 (mscene.RegionInfo.InternalEndPoint.Port == ipEndPoint.Port)) 370 return true;
439 {
440 scene = mscene;
441 return true;
442 }
443 } 371 }
444 } 372 }
445 373
@@ -504,15 +432,10 @@ namespace OpenSim.Region.Framework.Scenes
504 432
505 public RegionInfo GetRegionInfo(UUID regionID) 433 public RegionInfo GetRegionInfo(UUID regionID)
506 { 434 {
507 lock (m_localScenes) 435 Scene s;
436 if (m_localScenes.TryGetValue(regionID, out s))
508 { 437 {
509 foreach (Scene scene in m_localScenes) 438 return s.RegionInfo;
510 {
511 if (scene.RegionInfo.RegionID == regionID)
512 {
513 return scene.RegionInfo;
514 }
515 }
516 } 439 }
517 440
518 return null; 441 return null;
@@ -530,14 +453,12 @@ namespace OpenSim.Region.Framework.Scenes
530 453
531 public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar) 454 public bool TryGetScenePresence(UUID avatarId, out ScenePresence avatar)
532 { 455 {
533 lock (m_localScenes) 456 List<Scene> sceneList = Scenes;
457 foreach (Scene scene in sceneList)
534 { 458 {
535 foreach (Scene scene in m_localScenes) 459 if (scene.TryGetScenePresence(avatarId, out avatar))
536 { 460 {
537 if (scene.TryGetScenePresence(avatarId, out avatar)) 461 return true;
538 {
539 return true;
540 }
541 } 462 }
542 } 463 }
543 464
@@ -547,15 +468,13 @@ namespace OpenSim.Region.Framework.Scenes
547 468
548 public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar) 469 public bool TryGetRootScenePresence(UUID avatarId, out ScenePresence avatar)
549 { 470 {
550 lock (m_localScenes) 471 List<Scene> sceneList = Scenes;
472 foreach (Scene scene in sceneList)
551 { 473 {
552 foreach (Scene scene in m_localScenes) 474 avatar = scene.GetScenePresence(avatarId);
553 {
554 avatar = scene.GetScenePresence(avatarId);
555 475
556 if (avatar != null && !avatar.IsChildAgent) 476 if (avatar != null && !avatar.IsChildAgent)
557 return true; 477 return true;
558 }
559 } 478 }
560 479
561 avatar = null; 480 avatar = null;
@@ -564,22 +483,19 @@ namespace OpenSim.Region.Framework.Scenes
564 483
565 public void CloseScene(Scene scene) 484 public void CloseScene(Scene scene)
566 { 485 {
567 lock (m_localScenes) 486 m_localScenes.Remove(scene.RegionInfo.RegionID);
568 m_localScenes.Remove(scene);
569 487
570 scene.Close(); 488 scene.Close();
571 } 489 }
572 490
573 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar) 491 public bool TryGetAvatarByName(string avatarName, out ScenePresence avatar)
574 { 492 {
575 lock (m_localScenes) 493 List<Scene> sceneList = Scenes;
494 foreach (Scene scene in sceneList)
576 { 495 {
577 foreach (Scene scene in m_localScenes) 496 if (scene.TryGetAvatarByName(avatarName, out avatar))
578 { 497 {
579 if (scene.TryGetAvatarByName(avatarName, out avatar)) 498 return true;
580 {
581 return true;
582 }
583 } 499 }
584 } 500 }
585 501
@@ -589,14 +505,12 @@ namespace OpenSim.Region.Framework.Scenes
589 505
590 public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp) 506 public bool TryGetRootScenePresenceByName(string firstName, string lastName, out ScenePresence sp)
591 { 507 {
592 lock (m_localScenes) 508 List<Scene> sceneList = Scenes;
509 foreach (Scene scene in sceneList)
593 { 510 {
594 foreach (Scene scene in m_localScenes) 511 sp = scene.GetScenePresence(firstName, lastName);
595 { 512 if (sp != null && !sp.IsChildAgent)
596 sp = scene.GetScenePresence(firstName, lastName); 513 return true;
597 if (sp != null && !sp.IsChildAgent)
598 return true;
599 }
600 } 514 }
601 515
602 sp = null; 516 sp = null;
@@ -605,8 +519,8 @@ namespace OpenSim.Region.Framework.Scenes
605 519
606 public void ForEachScene(Action<Scene> action) 520 public void ForEachScene(Action<Scene> action)
607 { 521 {
608 lock (m_localScenes) 522 List<Scene> sceneList = Scenes;
609 m_localScenes.ForEach(action); 523 sceneList.ForEach(action);
610 } 524 }
611 } 525 }
612} 526}
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 20d7a01..46a7e3d 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; }
@@ -391,7 +465,15 @@ namespace OpenSim.Region.Framework.Scenes
391 { 465 {
392 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); 466 return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0));
393 } 467 }
394 468
469
470
471 private struct avtocrossInfo
472 {
473 public ScenePresence av;
474 public uint ParentID;
475 }
476
395 /// <summary> 477 /// <summary>
396 /// The absolute position of this scene object in the scene 478 /// The absolute position of this scene object in the scene
397 /// </summary> 479 /// </summary>
@@ -404,14 +486,128 @@ namespace OpenSim.Region.Framework.Scenes
404 486
405 if (Scene != null) 487 if (Scene != null)
406 { 488 {
407 if ((Scene.TestBorderCross(val - Vector3.UnitX, Cardinals.E) || Scene.TestBorderCross(val + Vector3.UnitX, Cardinals.W) 489 // 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)) 490 // || Scene.TestBorderCross(val - Vector3.UnitY, Cardinals.N) || Scene.TestBorderCross(val + Vector3.UnitY, Cardinals.S))
491 // && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
492 if ((Scene.TestBorderCross(val, Cardinals.E) || Scene.TestBorderCross(val, Cardinals.W)
493 || Scene.TestBorderCross(val, Cardinals.N) || Scene.TestBorderCross(val, Cardinals.S))
409 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) 494 && !IsAttachmentCheckFull() && (!Scene.LoadingPrims))
410 { 495 {
411 m_scene.CrossPrimGroupIntoNewRegion(val, this, true); 496 IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface<IEntityTransferModule>();
497 uint x = 0;
498 uint y = 0;
499 string version = String.Empty;
500 Vector3 newpos = Vector3.Zero;
501 OpenSim.Services.Interfaces.GridRegion destination = null;
502
503 bool canCross = true;
504 foreach (ScenePresence av in m_linkedAvatars)
505 {
506 // We need to cross these agents. First, let's find
507 // out if any of them can't cross for some reason.
508 // We have to deny the crossing entirely if any
509 // of them are banned. Alternatively, we could
510 // unsit banned agents....
511
512
513 // We set the avatar position as being the object
514 // position to get the region to send to
515 if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null)
516 {
517 canCross = false;
518 break;
519 }
520
521 m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName);
522 }
523
524 if (canCross)
525 {
526 // We unparent the SP quietly so that it won't
527 // be made to stand up
528
529 List<avtocrossInfo> avsToCross = new List<avtocrossInfo>();
530
531 foreach (ScenePresence av in m_linkedAvatars)
532 {
533 avtocrossInfo avinfo = new avtocrossInfo();
534 SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID);
535 if (parentPart != null)
536 av.ParentUUID = parentPart.UUID;
537
538 avinfo.av = av;
539 avinfo.ParentID = av.ParentID;
540 avsToCross.Add(avinfo);
541
542 av.ParentID = 0;
543 }
544
545// m_linkedAvatars.Clear();
546 m_scene.CrossPrimGroupIntoNewRegion(val, this, true);
547
548 // Normalize
549 if (val.X >= Constants.RegionSize)
550 val.X -= Constants.RegionSize;
551 if (val.Y >= Constants.RegionSize)
552 val.Y -= Constants.RegionSize;
553 if (val.X < 0)
554 val.X += Constants.RegionSize;
555 if (val.Y < 0)
556 val.Y += Constants.RegionSize;
557
558 // If it's deleted, crossing was successful
559 if (IsDeleted)
560 {
561 // foreach (ScenePresence av in m_linkedAvatars)
562 foreach (avtocrossInfo avinfo in avsToCross)
563 {
564 ScenePresence av = avinfo.av;
565 if (!av.IsInTransit) // just in case...
566 {
567 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val);
568
569 av.IsInTransit = true;
570
571 CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync;
572 d.BeginInvoke(av, val, x, y, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d);
573 }
574 else
575 m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val);
576 }
577 avsToCross.Clear();
578 return;
579 }
580 else // cross failed, put avas back ??
581 {
582 foreach (avtocrossInfo avinfo in avsToCross)
583 {
584 ScenePresence av = avinfo.av;
585 av.ParentUUID = UUID.Zero;
586 av.ParentID = avinfo.ParentID;
587// m_linkedAvatars.Add(av);
588 }
589 }
590 avsToCross.Clear();
591
592 }
593 else if (RootPart.PhysActor != null)
594 {
595 RootPart.PhysActor.CrossingFailure();
596 }
597
598 Vector3 oldp = AbsolutePosition;
599 val.X = Util.Clamp<float>(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f);
600 val.Y = Util.Clamp<float>(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f);
601 val.Z = Util.Clamp<float>(oldp.Z, 0.5f, 4096.0f);
412 } 602 }
413 } 603 }
414 604
605/* don't see the need but worse don't see where is restored to false if things stay in
606 foreach (SceneObjectPart part in m_parts.GetArray())
607 {
608 part.IgnoreUndoUpdate = true;
609 }
610 */
415 if (RootPart.GetStatusSandbox()) 611 if (RootPart.GetStatusSandbox())
416 { 612 {
417 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) 613 if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10)
@@ -425,10 +621,30 @@ namespace OpenSim.Region.Framework.Scenes
425 return; 621 return;
426 } 622 }
427 } 623 }
428
429 SceneObjectPart[] parts = m_parts.GetArray(); 624 SceneObjectPart[] parts = m_parts.GetArray();
430 for (int i = 0; i < parts.Length; i++) 625 bool triggerScriptEvent = m_rootPart.GroupPosition != val;
431 parts[i].GroupPosition = val; 626 if (m_dupeInProgress)
627 triggerScriptEvent = false;
628 foreach (SceneObjectPart part in parts)
629 {
630 part.GroupPosition = val;
631 if (triggerScriptEvent)
632 part.TriggerScriptChangedEvent(Changed.POSITION);
633 }
634 if (!m_dupeInProgress)
635 {
636 foreach (ScenePresence av in m_linkedAvatars)
637 {
638 SceneObjectPart p = m_scene.GetSceneObjectPart(av.ParentID);
639 if (p != null && m_parts.TryGetValue(p.UUID, out p))
640 {
641 Vector3 offset = p.GetWorldPosition() - av.ParentPosition;
642 av.AbsolutePosition += offset;
643 av.ParentPosition = p.GetWorldPosition(); //ParentPosition gets cleared by AbsolutePosition
644 av.SendAvatarDataToAllAgents();
645 }
646 }
647 }
432 648
433 //if (m_rootPart.PhysActor != null) 649 //if (m_rootPart.PhysActor != null)
434 //{ 650 //{
@@ -443,6 +659,40 @@ namespace OpenSim.Region.Framework.Scenes
443 } 659 }
444 } 660 }
445 661
662 public override Vector3 Velocity
663 {
664 get { return RootPart.Velocity; }
665 set { RootPart.Velocity = value; }
666 }
667
668 private void CrossAgentToNewRegionCompleted(IAsyncResult iar)
669 {
670 CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState;
671 ScenePresence agent = icon.EndInvoke(iar);
672
673 //// If the cross was successful, this agent is a child agent
674 if (agent.IsChildAgent)
675 {
676 if (agent.ParentUUID != UUID.Zero)
677 {
678 agent.ParentPart = null;
679 agent.ParentPosition = Vector3.Zero;
680 // agent.ParentUUID = UUID.Zero;
681 }
682 }
683
684 agent.ParentUUID = UUID.Zero;
685
686// agent.Reset();
687// else // Not successful
688// agent.RestoreInCurrentScene();
689
690 // In any case
691 agent.IsInTransit = false;
692
693 m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname);
694 }
695
446 public override uint LocalId 696 public override uint LocalId
447 { 697 {
448 get { return m_rootPart.LocalId; } 698 get { return m_rootPart.LocalId; }
@@ -513,6 +763,11 @@ namespace OpenSim.Region.Framework.Scenes
513 m_isSelected = value; 763 m_isSelected = value;
514 // Tell physics engine that group is selected 764 // Tell physics engine that group is selected
515 765
766 // this is not right
767 // but ode engines should only really need to know about root part
768 // so they can put entire object simulation on hold and not colliding
769 // keep as was for now
770
516 PhysicsActor pa = m_rootPart.PhysActor; 771 PhysicsActor pa = m_rootPart.PhysActor;
517 if (pa != null) 772 if (pa != null)
518 { 773 {
@@ -529,6 +784,42 @@ namespace OpenSim.Region.Framework.Scenes
529 childPa.Selected = value; 784 childPa.Selected = value;
530 } 785 }
531 } 786 }
787 if (RootPart.KeyframeMotion != null)
788 RootPart.KeyframeMotion.Selected = value;
789 }
790 }
791
792 public void PartSelectChanged(bool partSelect)
793 {
794 // any part selected makes group selected
795 if (m_isSelected == partSelect)
796 return;
797
798 if (partSelect)
799 {
800 IsSelected = partSelect;
801// if (!IsAttachment)
802// ScheduleGroupForFullUpdate();
803 }
804 else
805 {
806 // bad bad bad 2 heavy for large linksets
807 // since viewer does send lot of (un)selects
808 // this needs to be replaced by a specific list or count ?
809 // but that will require extra code in several places
810
811 SceneObjectPart[] parts = m_parts.GetArray();
812 for (int i = 0; i < parts.Length; i++)
813 {
814 SceneObjectPart part = parts[i];
815 if (part.IsSelected)
816 return;
817 }
818 IsSelected = partSelect;
819 if (!IsAttachment)
820 {
821 ScheduleGroupForFullUpdate();
822 }
532 } 823 }
533 } 824 }
534 825
@@ -606,6 +897,7 @@ namespace OpenSim.Region.Framework.Scenes
606 /// </summary> 897 /// </summary>
607 public SceneObjectGroup() 898 public SceneObjectGroup()
608 { 899 {
900
609 } 901 }
610 902
611 /// <summary> 903 /// <summary>
@@ -622,7 +914,7 @@ namespace OpenSim.Region.Framework.Scenes
622 /// Constructor. This object is added to the scene later via AttachToScene() 914 /// Constructor. This object is added to the scene later via AttachToScene()
623 /// </summary> 915 /// </summary>
624 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) 916 public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape)
625 { 917 {
626 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); 918 SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero));
627 } 919 }
628 920
@@ -658,6 +950,9 @@ namespace OpenSim.Region.Framework.Scenes
658 /// </summary> 950 /// </summary>
659 public virtual void AttachToBackup() 951 public virtual void AttachToBackup()
660 { 952 {
953 if (IsAttachment) return;
954 m_scene.SceneGraph.FireAttachToBackup(this);
955
661 if (InSceneBackup) 956 if (InSceneBackup)
662 { 957 {
663 //m_log.DebugFormat( 958 //m_log.DebugFormat(
@@ -700,6 +995,13 @@ namespace OpenSim.Region.Framework.Scenes
700 995
701 ApplyPhysics(); 996 ApplyPhysics();
702 997
998 if (RootPart.PhysActor != null)
999 RootPart.Force = RootPart.Force;
1000 if (RootPart.PhysActor != null)
1001 RootPart.Torque = RootPart.Torque;
1002 if (RootPart.PhysActor != null)
1003 RootPart.Buoyancy = RootPart.Buoyancy;
1004
703 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled 1005 // Don't trigger the update here - otherwise some client issues occur when multiple updates are scheduled
704 // for the same object with very different properties. The caller must schedule the update. 1006 // for the same object with very different properties. The caller must schedule the update.
705 //ScheduleGroupForFullUpdate(); 1007 //ScheduleGroupForFullUpdate();
@@ -715,6 +1017,10 @@ namespace OpenSim.Region.Framework.Scenes
715 EntityIntersection result = new EntityIntersection(); 1017 EntityIntersection result = new EntityIntersection();
716 1018
717 SceneObjectPart[] parts = m_parts.GetArray(); 1019 SceneObjectPart[] parts = m_parts.GetArray();
1020
1021 // Find closest hit here
1022 float idist = float.MaxValue;
1023
718 for (int i = 0; i < parts.Length; i++) 1024 for (int i = 0; i < parts.Length; i++)
719 { 1025 {
720 SceneObjectPart part = parts[i]; 1026 SceneObjectPart part = parts[i];
@@ -729,11 +1035,6 @@ namespace OpenSim.Region.Framework.Scenes
729 1035
730 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters); 1036 EntityIntersection inter = part.TestIntersectionOBB(hRay, parentrotation, frontFacesOnly, faceCenters);
731 1037
732 // This may need to be updated to the maximum draw distance possible..
733 // We might (and probably will) be checking for prim creation from other sims
734 // when the camera crosses the border.
735 float idist = Constants.RegionSize;
736
737 if (inter.HitTF) 1038 if (inter.HitTF)
738 { 1039 {
739 // We need to find the closest prim to return to the testcaller along the ray 1040 // We need to find the closest prim to return to the testcaller along the ray
@@ -744,10 +1045,11 @@ namespace OpenSim.Region.Framework.Scenes
744 result.obj = part; 1045 result.obj = part;
745 result.normal = inter.normal; 1046 result.normal = inter.normal;
746 result.distance = inter.distance; 1047 result.distance = inter.distance;
1048
1049 idist = inter.distance;
747 } 1050 }
748 } 1051 }
749 } 1052 }
750
751 return result; 1053 return result;
752 } 1054 }
753 1055
@@ -759,25 +1061,27 @@ namespace OpenSim.Region.Framework.Scenes
759 /// <returns></returns> 1061 /// <returns></returns>
760 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ) 1062 public void GetAxisAlignedBoundingBoxRaw(out float minX, out float maxX, out float minY, out float maxY, out float minZ, out float maxZ)
761 { 1063 {
762 maxX = -256f; 1064 maxX = float.MinValue;
763 maxY = -256f; 1065 maxY = float.MinValue;
764 maxZ = -256f; 1066 maxZ = float.MinValue;
765 minX = 256f; 1067 minX = float.MaxValue;
766 minY = 256f; 1068 minY = float.MaxValue;
767 minZ = 8192f; 1069 minZ = float.MaxValue;
768 1070
769 SceneObjectPart[] parts = m_parts.GetArray(); 1071 SceneObjectPart[] parts = m_parts.GetArray();
770 for (int i = 0; i < parts.Length; i++) 1072 foreach (SceneObjectPart part in parts)
771 { 1073 {
772 SceneObjectPart part = parts[i];
773
774 Vector3 worldPos = part.GetWorldPosition(); 1074 Vector3 worldPos = part.GetWorldPosition();
775 Vector3 offset = worldPos - AbsolutePosition; 1075 Vector3 offset = worldPos - AbsolutePosition;
776 Quaternion worldRot; 1076 Quaternion worldRot;
777 if (part.ParentID == 0) 1077 if (part.ParentID == 0)
1078 {
778 worldRot = part.RotationOffset; 1079 worldRot = part.RotationOffset;
1080 }
779 else 1081 else
1082 {
780 worldRot = part.GetWorldRotation(); 1083 worldRot = part.GetWorldRotation();
1084 }
781 1085
782 Vector3 frontTopLeft; 1086 Vector3 frontTopLeft;
783 Vector3 frontTopRight; 1087 Vector3 frontTopRight;
@@ -789,6 +1093,8 @@ namespace OpenSim.Region.Framework.Scenes
789 Vector3 backBottomLeft; 1093 Vector3 backBottomLeft;
790 Vector3 backBottomRight; 1094 Vector3 backBottomRight;
791 1095
1096 // Vector3[] corners = new Vector3[8];
1097
792 Vector3 orig = Vector3.Zero; 1098 Vector3 orig = Vector3.Zero;
793 1099
794 frontTopLeft.X = orig.X - (part.Scale.X / 2); 1100 frontTopLeft.X = orig.X - (part.Scale.X / 2);
@@ -823,6 +1129,38 @@ namespace OpenSim.Region.Framework.Scenes
823 backBottomRight.Y = orig.Y + (part.Scale.Y / 2); 1129 backBottomRight.Y = orig.Y + (part.Scale.Y / 2);
824 backBottomRight.Z = orig.Z - (part.Scale.Z / 2); 1130 backBottomRight.Z = orig.Z - (part.Scale.Z / 2);
825 1131
1132
1133
1134 //m_log.InfoFormat("pre corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1135 //m_log.InfoFormat("pre corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1136 //m_log.InfoFormat("pre corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1137 //m_log.InfoFormat("pre corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1138 //m_log.InfoFormat("pre corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1139 //m_log.InfoFormat("pre corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1140 //m_log.InfoFormat("pre corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1141 //m_log.InfoFormat("pre corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1142
1143 //for (int i = 0; i < 8; i++)
1144 //{
1145 // corners[i] = corners[i] * worldRot;
1146 // corners[i] += offset;
1147
1148 // if (corners[i].X > maxX)
1149 // maxX = corners[i].X;
1150 // if (corners[i].X < minX)
1151 // minX = corners[i].X;
1152
1153 // if (corners[i].Y > maxY)
1154 // maxY = corners[i].Y;
1155 // if (corners[i].Y < minY)
1156 // minY = corners[i].Y;
1157
1158 // if (corners[i].Z > maxZ)
1159 // maxZ = corners[i].Y;
1160 // if (corners[i].Z < minZ)
1161 // minZ = corners[i].Z;
1162 //}
1163
826 frontTopLeft = frontTopLeft * worldRot; 1164 frontTopLeft = frontTopLeft * worldRot;
827 frontTopRight = frontTopRight * worldRot; 1165 frontTopRight = frontTopRight * worldRot;
828 frontBottomLeft = frontBottomLeft * worldRot; 1166 frontBottomLeft = frontBottomLeft * worldRot;
@@ -844,6 +1182,15 @@ namespace OpenSim.Region.Framework.Scenes
844 backTopLeft += offset; 1182 backTopLeft += offset;
845 backTopRight += offset; 1183 backTopRight += offset;
846 1184
1185 //m_log.InfoFormat("corner 1 is {0} {1} {2}", frontTopLeft.X, frontTopLeft.Y, frontTopLeft.Z);
1186 //m_log.InfoFormat("corner 2 is {0} {1} {2}", frontTopRight.X, frontTopRight.Y, frontTopRight.Z);
1187 //m_log.InfoFormat("corner 3 is {0} {1} {2}", frontBottomRight.X, frontBottomRight.Y, frontBottomRight.Z);
1188 //m_log.InfoFormat("corner 4 is {0} {1} {2}", frontBottomLeft.X, frontBottomLeft.Y, frontBottomLeft.Z);
1189 //m_log.InfoFormat("corner 5 is {0} {1} {2}", backTopLeft.X, backTopLeft.Y, backTopLeft.Z);
1190 //m_log.InfoFormat("corner 6 is {0} {1} {2}", backTopRight.X, backTopRight.Y, backTopRight.Z);
1191 //m_log.InfoFormat("corner 7 is {0} {1} {2}", backBottomRight.X, backBottomRight.Y, backBottomRight.Z);
1192 //m_log.InfoFormat("corner 8 is {0} {1} {2}", backBottomLeft.X, backBottomLeft.Y, backBottomLeft.Z);
1193
847 if (frontTopRight.X > maxX) 1194 if (frontTopRight.X > maxX)
848 maxX = frontTopRight.X; 1195 maxX = frontTopRight.X;
849 if (frontTopLeft.X > maxX) 1196 if (frontTopLeft.X > maxX)
@@ -987,17 +1334,118 @@ namespace OpenSim.Region.Framework.Scenes
987 1334
988 #endregion 1335 #endregion
989 1336
1337 public void GetResourcesCosts(SceneObjectPart apart,
1338 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1339 {
1340 // this information may need to be cached
1341
1342 float cost;
1343 float tmpcost;
1344
1345 bool ComplexCost = false;
1346
1347 SceneObjectPart p;
1348 SceneObjectPart[] parts;
1349
1350 lock (m_parts)
1351 {
1352 parts = m_parts.GetArray();
1353 }
1354
1355 int nparts = parts.Length;
1356
1357
1358 for (int i = 0; i < nparts; i++)
1359 {
1360 p = parts[i];
1361
1362 if (p.UsesComplexCost)
1363 {
1364 ComplexCost = true;
1365 break;
1366 }
1367 }
1368
1369 if (ComplexCost)
1370 {
1371 linksetResCost = 0;
1372 linksetPhysCost = 0;
1373 partCost = 0;
1374 partPhysCost = 0;
1375
1376 for (int i = 0; i < nparts; i++)
1377 {
1378 p = parts[i];
1379
1380 cost = p.StreamingCost;
1381 tmpcost = p.SimulationCost;
1382 if (tmpcost > cost)
1383 cost = tmpcost;
1384 tmpcost = p.PhysicsCost;
1385 if (tmpcost > cost)
1386 cost = tmpcost;
1387
1388 linksetPhysCost += tmpcost;
1389 linksetResCost += cost;
1390
1391 if (p == apart)
1392 {
1393 partCost = cost;
1394 partPhysCost = tmpcost;
1395 }
1396 }
1397 }
1398 else
1399 {
1400 partPhysCost = 1.0f;
1401 partCost = 1.0f;
1402 linksetResCost = (float)nparts;
1403 linksetPhysCost = linksetResCost;
1404 }
1405 }
1406
1407 public void GetSelectedCosts(out float PhysCost, out float StreamCost, out float SimulCost)
1408 {
1409 SceneObjectPart p;
1410 SceneObjectPart[] parts;
1411
1412 lock (m_parts)
1413 {
1414 parts = m_parts.GetArray();
1415 }
1416
1417 int nparts = parts.Length;
1418
1419 PhysCost = 0;
1420 StreamCost = 0;
1421 SimulCost = 0;
1422
1423 for (int i = 0; i < nparts; i++)
1424 {
1425 p = parts[i];
1426
1427 StreamCost += p.StreamingCost;
1428 SimulCost += p.SimulationCost;
1429 PhysCost += p.PhysicsCost;
1430 }
1431 }
1432
990 public void SaveScriptedState(XmlTextWriter writer) 1433 public void SaveScriptedState(XmlTextWriter writer)
991 { 1434 {
1435 SaveScriptedState(writer, false);
1436 }
1437
1438 public void SaveScriptedState(XmlTextWriter writer, bool oldIDs)
1439 {
992 XmlDocument doc = new XmlDocument(); 1440 XmlDocument doc = new XmlDocument();
993 Dictionary<UUID,string> states = new Dictionary<UUID,string>(); 1441 Dictionary<UUID,string> states = new Dictionary<UUID,string>();
994 1442
995 SceneObjectPart[] parts = m_parts.GetArray(); 1443 SceneObjectPart[] parts = m_parts.GetArray();
996 for (int i = 0; i < parts.Length; i++) 1444 for (int i = 0; i < parts.Length; i++)
997 { 1445 {
998 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(); 1446 Dictionary<UUID, string> pstates = parts[i].Inventory.GetScriptStates(oldIDs);
999 foreach (KeyValuePair<UUID, string> kvp in pstates) 1447 foreach (KeyValuePair<UUID, string> kvp in pstates)
1000 states.Add(kvp.Key, kvp.Value); 1448 states[kvp.Key] = kvp.Value;
1001 } 1449 }
1002 1450
1003 if (states.Count > 0) 1451 if (states.Count > 0)
@@ -1017,6 +1465,169 @@ namespace OpenSim.Region.Framework.Scenes
1017 } 1465 }
1018 1466
1019 /// <summary> 1467 /// <summary>
1468 /// Add the avatar to this linkset (avatar is sat).
1469 /// </summary>
1470 /// <param name="agentID"></param>
1471 public void AddAvatar(UUID agentID)
1472 {
1473 ScenePresence presence;
1474 if (m_scene.TryGetScenePresence(agentID, out presence))
1475 {
1476 if (!m_linkedAvatars.Contains(presence))
1477 {
1478 m_linkedAvatars.Add(presence);
1479 }
1480 }
1481 }
1482
1483 /// <summary>
1484 /// Delete the avatar from this linkset (avatar is unsat).
1485 /// </summary>
1486 /// <param name="agentID"></param>
1487 public void DeleteAvatar(UUID agentID)
1488 {
1489 ScenePresence presence;
1490 if (m_scene.TryGetScenePresence(agentID, out presence))
1491 {
1492 if (m_linkedAvatars.Contains(presence))
1493 {
1494 m_linkedAvatars.Remove(presence);
1495 }
1496 }
1497 }
1498
1499 /// <summary>
1500 /// Returns the list of linked presences (avatars sat on this group)
1501 /// </summary>
1502 /// <param name="agentID"></param>
1503 public List<ScenePresence> GetLinkedAvatars()
1504 {
1505 return m_linkedAvatars;
1506 }
1507
1508 /// <summary>
1509 /// Attach this scene object to the given avatar.
1510 /// </summary>
1511 /// <param name="agentID"></param>
1512 /// <param name="attachmentpoint"></param>
1513 /// <param name="AttachOffset"></param>
1514 private void AttachToAgent(
1515 ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
1516 {
1517 if (avatar != null)
1518 {
1519 // don't attach attachments to child agents
1520 if (avatar.IsChildAgent) return;
1521
1522 // Remove from database and parcel prim count
1523 m_scene.DeleteFromStorage(so.UUID);
1524 m_scene.EventManager.TriggerParcelPrimCountTainted();
1525
1526 so.AttachedAvatar = avatar.UUID;
1527
1528 if (so.RootPart.PhysActor != null)
1529 {
1530 m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor);
1531 so.RootPart.PhysActor = null;
1532 }
1533
1534 so.AbsolutePosition = attachOffset;
1535 so.RootPart.AttachedPos = attachOffset;
1536 so.IsAttachment = true;
1537 so.RootPart.SetParentLocalId(avatar.LocalId);
1538 so.AttachmentPoint = attachmentpoint;
1539
1540 avatar.AddAttachment(this);
1541
1542 if (!silent)
1543 {
1544 // Killing it here will cause the client to deselect it
1545 // It then reappears on the avatar, deselected
1546 // through the full update below
1547 //
1548 if (IsSelected)
1549 {
1550 m_scene.SendKillObject(new List<uint> { m_rootPart.LocalId });
1551 }
1552
1553 IsSelected = false; // fudge....
1554 ScheduleGroupForFullUpdate();
1555 }
1556 }
1557 else
1558 {
1559 m_log.WarnFormat(
1560 "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present",
1561 UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName);
1562 }
1563 }
1564
1565 public byte GetAttachmentPoint()
1566 {
1567 return m_rootPart.Shape.State;
1568 }
1569
1570 public void DetachToGround()
1571 {
1572 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1573 if (avatar == null)
1574 return;
1575
1576 avatar.RemoveAttachment(this);
1577
1578 Vector3 detachedpos = new Vector3(127f,127f,127f);
1579 if (avatar == null)
1580 return;
1581
1582 detachedpos = avatar.AbsolutePosition;
1583 FromItemID = UUID.Zero;
1584
1585 AbsolutePosition = detachedpos;
1586 AttachedAvatar = UUID.Zero;
1587
1588 //SceneObjectPart[] parts = m_parts.GetArray();
1589 //for (int i = 0; i < parts.Length; i++)
1590 // parts[i].AttachedAvatar = UUID.Zero;
1591
1592 m_rootPart.SetParentLocalId(0);
1593 AttachmentPoint = (byte)0;
1594 // must check if buildind should be true or false here
1595 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive,false);
1596 HasGroupChanged = true;
1597 RootPart.Rezzed = DateTime.Now;
1598 RootPart.RemFlag(PrimFlags.TemporaryOnRez);
1599 AttachToBackup();
1600 m_scene.EventManager.TriggerParcelPrimCountTainted();
1601 m_rootPart.ScheduleFullUpdate();
1602 m_rootPart.ClearUndoState();
1603 }
1604
1605 public void DetachToInventoryPrep()
1606 {
1607 ScenePresence avatar = m_scene.GetScenePresence(AttachedAvatar);
1608 //Vector3 detachedpos = new Vector3(127f, 127f, 127f);
1609 if (avatar != null)
1610 {
1611 //detachedpos = avatar.AbsolutePosition;
1612 avatar.RemoveAttachment(this);
1613 }
1614
1615 AttachedAvatar = UUID.Zero;
1616
1617 /*SceneObjectPart[] parts = m_parts.GetArray();
1618 for (int i = 0; i < parts.Length; i++)
1619 parts[i].AttachedAvatar = UUID.Zero;*/
1620
1621 m_rootPart.SetParentLocalId(0);
1622 //m_rootPart.SetAttachmentPoint((byte)0);
1623 IsAttachment = false;
1624 AbsolutePosition = m_rootPart.AttachedPos;
1625 //m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_scene.m_physicalPrim);
1626 //AttachToBackup();
1627 //m_rootPart.ScheduleFullUpdate();
1628 }
1629
1630 /// <summary>
1020 /// 1631 ///
1021 /// </summary> 1632 /// </summary>
1022 /// <param name="part"></param> 1633 /// <param name="part"></param>
@@ -1066,7 +1677,10 @@ namespace OpenSim.Region.Framework.Scenes
1066 public void AddPart(SceneObjectPart part) 1677 public void AddPart(SceneObjectPart part)
1067 { 1678 {
1068 part.SetParent(this); 1679 part.SetParent(this);
1069 part.LinkNum = m_parts.Add(part.UUID, part); 1680 m_parts.Add(part.UUID, part);
1681
1682 part.LinkNum = m_parts.Count;
1683
1070 if (part.LinkNum == 2) 1684 if (part.LinkNum == 2)
1071 RootPart.LinkNum = 1; 1685 RootPart.LinkNum = 1;
1072 } 1686 }
@@ -1154,7 +1768,7 @@ namespace OpenSim.Region.Framework.Scenes
1154// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}", 1768// "[SCENE OBJECT GROUP]: Processing OnGrabPart for {0} on {1} {2}, offsetPos {3}",
1155// remoteClient.Name, part.Name, part.LocalId, offsetPos); 1769// remoteClient.Name, part.Name, part.LocalId, offsetPos);
1156 1770
1157 part.StoreUndoState(); 1771// part.StoreUndoState();
1158 part.OnGrab(offsetPos, remoteClient); 1772 part.OnGrab(offsetPos, remoteClient);
1159 } 1773 }
1160 1774
@@ -1174,6 +1788,11 @@ namespace OpenSim.Region.Framework.Scenes
1174 /// <param name="silent">If true then deletion is not broadcast to clients</param> 1788 /// <param name="silent">If true then deletion is not broadcast to clients</param>
1175 public void DeleteGroupFromScene(bool silent) 1789 public void DeleteGroupFromScene(bool silent)
1176 { 1790 {
1791 // We need to keep track of this state in case this group is still queued for backup.
1792 IsDeleted = true;
1793
1794 DetachFromBackup();
1795
1177 SceneObjectPart[] parts = m_parts.GetArray(); 1796 SceneObjectPart[] parts = m_parts.GetArray();
1178 for (int i = 0; i < parts.Length; i++) 1797 for (int i = 0; i < parts.Length; i++)
1179 { 1798 {
@@ -1189,13 +1808,14 @@ namespace OpenSim.Region.Framework.Scenes
1189 part.ClearUpdateSchedule(); 1808 part.ClearUpdateSchedule();
1190 if (part == m_rootPart) 1809 if (part == m_rootPart)
1191 { 1810 {
1192 if (!IsAttachment || (AttachedAvatar == avatar.ControllingClient.AgentId) || 1811 if (!IsAttachment || (AttachedAvatar == avatar.ControllingClient.AgentId) ||
1193 (AttachmentPoint < 31) || (AttachmentPoint > 38)) 1812 (AttachmentPoint < 31) || (AttachmentPoint > 38))
1194 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId }); 1813 avatar.ControllingClient.SendKillObject(m_regionHandle, new List<uint> { part.LocalId });
1195 } 1814 }
1196 } 1815 }
1197 }); 1816 });
1198 } 1817 }
1818
1199 } 1819 }
1200 1820
1201 public void AddScriptLPS(int count) 1821 public void AddScriptLPS(int count)
@@ -1265,28 +1885,43 @@ namespace OpenSim.Region.Framework.Scenes
1265 /// </summary> 1885 /// </summary>
1266 public void ApplyPhysics() 1886 public void ApplyPhysics()
1267 { 1887 {
1268 // Apply physics to the root prim
1269 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive);
1270
1271 // Apply physics to child prims
1272 SceneObjectPart[] parts = m_parts.GetArray(); 1888 SceneObjectPart[] parts = m_parts.GetArray();
1273 if (parts.Length > 1) 1889 if (parts.Length > 1)
1274 { 1890 {
1891 ResetChildPrimPhysicsPositions();
1892
1893 // Apply physics to the root prim
1894 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, true);
1895
1896
1275 for (int i = 0; i < parts.Length; i++) 1897 for (int i = 0; i < parts.Length; i++)
1276 { 1898 {
1277 SceneObjectPart part = parts[i]; 1899 SceneObjectPart part = parts[i];
1278 if (part.LocalId != m_rootPart.LocalId) 1900 if (part.LocalId != m_rootPart.LocalId)
1279 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive); 1901 part.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), part.VolumeDetectActive, true);
1280 } 1902 }
1281
1282 // Hack to get the physics scene geometries in the right spot 1903 // Hack to get the physics scene geometries in the right spot
1283 ResetChildPrimPhysicsPositions(); 1904// ResetChildPrimPhysicsPositions();
1905 if (m_rootPart.PhysActor != null)
1906 {
1907 m_rootPart.PhysActor.Building = false;
1908 }
1909 }
1910 else
1911 {
1912 // Apply physics to the root prim
1913 m_rootPart.ApplyPhysics(m_rootPart.GetEffectiveObjectFlags(), m_rootPart.VolumeDetectActive, false);
1284 } 1914 }
1285 } 1915 }
1286 1916
1287 public void SetOwnerId(UUID userId) 1917 public void SetOwnerId(UUID userId)
1288 { 1918 {
1289 ForEachPart(delegate(SceneObjectPart part) { part.OwnerID = userId; }); 1919 ForEachPart(delegate(SceneObjectPart part)
1920 {
1921
1922 part.OwnerID = userId;
1923
1924 });
1290 } 1925 }
1291 1926
1292 public void ForEachPart(Action<SceneObjectPart> whatToDo) 1927 public void ForEachPart(Action<SceneObjectPart> whatToDo)
@@ -1318,11 +1953,17 @@ namespace OpenSim.Region.Framework.Scenes
1318 return; 1953 return;
1319 } 1954 }
1320 1955
1956 if ((RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
1957 return;
1958
1321 // Since this is the top of the section of call stack for backing up a particular scene object, don't let 1959 // Since this is the top of the section of call stack for backing up a particular scene object, don't let
1322 // any exception propogate upwards. 1960 // any exception propogate upwards.
1323 try 1961 try
1324 { 1962 {
1325 if (!m_scene.ShuttingDown) // if shutting down then there will be nothing to handle the return so leave till next restart 1963 if (!m_scene.ShuttingDown || // if shutting down then there will be nothing to handle the return so leave till next restart
1964 m_scene.LoginsDisabled || // We're starting up or doing maintenance, don't mess with things
1965 m_scene.LoadingPrims) // Land may not be valid yet
1966
1326 { 1967 {
1327 ILandObject parcel = m_scene.LandChannel.GetLandObject( 1968 ILandObject parcel = m_scene.LandChannel.GetLandObject(
1328 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y); 1969 m_rootPart.GroupPosition.X, m_rootPart.GroupPosition.Y);
@@ -1349,6 +1990,7 @@ namespace OpenSim.Region.Framework.Scenes
1349 } 1990 }
1350 } 1991 }
1351 } 1992 }
1993
1352 } 1994 }
1353 1995
1354 if (m_scene.UseBackup && HasGroupChanged) 1996 if (m_scene.UseBackup && HasGroupChanged)
@@ -1356,10 +1998,30 @@ namespace OpenSim.Region.Framework.Scenes
1356 // don't backup while it's selected or you're asking for changes mid stream. 1998 // don't backup while it's selected or you're asking for changes mid stream.
1357 if (isTimeToPersist() || forcedBackup) 1999 if (isTimeToPersist() || forcedBackup)
1358 { 2000 {
2001 if (m_rootPart.PhysActor != null &&
2002 (!m_rootPart.PhysActor.IsPhysical))
2003 {
2004 // Possible ghost prim
2005 if (m_rootPart.PhysActor.Position != m_rootPart.GroupPosition)
2006 {
2007 foreach (SceneObjectPart part in m_parts.GetArray())
2008 {
2009 // Re-set physics actor positions and
2010 // orientations
2011 part.GroupPosition = m_rootPart.GroupPosition;
2012 }
2013 }
2014 }
1359// m_log.DebugFormat( 2015// m_log.DebugFormat(
1360// "[SCENE]: Storing {0}, {1} in {2}", 2016// "[SCENE]: Storing {0}, {1} in {2}",
1361// Name, UUID, m_scene.RegionInfo.RegionName); 2017// Name, UUID, m_scene.RegionInfo.RegionName);
1362 2018
2019 if (RootPart.Shape.PCode == 9 && RootPart.Shape.State != 0)
2020 {
2021 RootPart.Shape.State = 0;
2022 ScheduleGroupForFullUpdate();
2023 }
2024
1363 SceneObjectGroup backup_group = Copy(false); 2025 SceneObjectGroup backup_group = Copy(false);
1364 backup_group.RootPart.Velocity = RootPart.Velocity; 2026 backup_group.RootPart.Velocity = RootPart.Velocity;
1365 backup_group.RootPart.Acceleration = RootPart.Acceleration; 2027 backup_group.RootPart.Acceleration = RootPart.Acceleration;
@@ -1373,6 +2035,11 @@ namespace OpenSim.Region.Framework.Scenes
1373 2035
1374 backup_group.ForEachPart(delegate(SceneObjectPart part) 2036 backup_group.ForEachPart(delegate(SceneObjectPart part)
1375 { 2037 {
2038 if (part.KeyframeMotion != null)
2039 {
2040 part.KeyframeMotion = KeyframeMotion.FromData(backup_group, part.KeyframeMotion.Serialize());
2041 part.KeyframeMotion.UpdateSceneObject(this);
2042 }
1376 part.Inventory.ProcessInventoryBackup(datastore); 2043 part.Inventory.ProcessInventoryBackup(datastore);
1377 }); 2044 });
1378 2045
@@ -1425,10 +2092,14 @@ namespace OpenSim.Region.Framework.Scenes
1425 /// <returns></returns> 2092 /// <returns></returns>
1426 public SceneObjectGroup Copy(bool userExposed) 2093 public SceneObjectGroup Copy(bool userExposed)
1427 { 2094 {
2095 m_dupeInProgress = true;
1428 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); 2096 SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone();
1429 dupe.m_isBackedUp = false; 2097 dupe.m_isBackedUp = false;
1430 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>(); 2098 dupe.m_parts = new MapAndArray<OpenMetaverse.UUID, SceneObjectPart>();
1431 2099
2100 // new group as no sitting avatars
2101 dupe.m_linkedAvatars = new List<ScenePresence>();
2102
1432 // Warning, The following code related to previousAttachmentStatus is needed so that clones of 2103 // Warning, The following code related to previousAttachmentStatus is needed so that clones of
1433 // attachments do not bordercross while they're being duplicated. This is hacktastic! 2104 // attachments do not bordercross while they're being duplicated. This is hacktastic!
1434 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region! 2105 // Normally, setting AbsolutePosition will bordercross a prim if it's outside the region!
@@ -1439,7 +2110,7 @@ namespace OpenSim.Region.Framework.Scenes
1439 // This is only necessary when userExposed is false! 2110 // This is only necessary when userExposed is false!
1440 2111
1441 bool previousAttachmentStatus = dupe.IsAttachment; 2112 bool previousAttachmentStatus = dupe.IsAttachment;
1442 2113
1443 if (!userExposed) 2114 if (!userExposed)
1444 dupe.IsAttachment = true; 2115 dupe.IsAttachment = true;
1445 2116
@@ -1457,11 +2128,11 @@ namespace OpenSim.Region.Framework.Scenes
1457 dupe.m_rootPart.TrimPermissions(); 2128 dupe.m_rootPart.TrimPermissions();
1458 2129
1459 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray()); 2130 List<SceneObjectPart> partList = new List<SceneObjectPart>(m_parts.GetArray());
1460 2131
1461 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) 2132 partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2)
1462 { 2133 {
1463 return p1.LinkNum.CompareTo(p2.LinkNum); 2134 return p1.LinkNum.CompareTo(p2.LinkNum);
1464 } 2135 }
1465 ); 2136 );
1466 2137
1467 foreach (SceneObjectPart part in partList) 2138 foreach (SceneObjectPart part in partList)
@@ -1471,41 +2142,53 @@ namespace OpenSim.Region.Framework.Scenes
1471 { 2142 {
1472 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); 2143 newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed);
1473 newPart.LinkNum = part.LinkNum; 2144 newPart.LinkNum = part.LinkNum;
1474 } 2145 if (userExposed)
2146 newPart.ParentID = dupe.m_rootPart.LocalId;
2147 }
1475 else 2148 else
1476 { 2149 {
1477 newPart = dupe.m_rootPart; 2150 newPart = dupe.m_rootPart;
1478 } 2151 }
2152/*
2153 bool isphys = ((newPart.Flags & PrimFlags.Physics) != 0);
2154 bool isphan = ((newPart.Flags & PrimFlags.Phantom) != 0);
1479 2155
1480 // Need to duplicate the physics actor as well 2156 // Need to duplicate the physics actor as well
1481 PhysicsActor originalPartPa = part.PhysActor; 2157 if (userExposed && (isphys || !isphan || newPart.VolumeDetectActive))
1482 if (originalPartPa != null && userExposed)
1483 { 2158 {
1484 PrimitiveBaseShape pbs = newPart.Shape; 2159 PrimitiveBaseShape pbs = newPart.Shape;
1485
1486 newPart.PhysActor 2160 newPart.PhysActor
1487 = m_scene.PhysicsScene.AddPrimShape( 2161 = m_scene.PhysicsScene.AddPrimShape(
1488 string.Format("{0}/{1}", newPart.Name, newPart.UUID), 2162 string.Format("{0}/{1}", newPart.Name, newPart.UUID),
1489 pbs, 2163 pbs,
1490 newPart.AbsolutePosition, 2164 newPart.AbsolutePosition,
1491 newPart.Scale, 2165 newPart.Scale,
1492 newPart.RotationOffset, 2166 newPart.GetWorldRotation(),
1493 originalPartPa.IsPhysical, 2167 isphys,
2168 isphan,
1494 newPart.LocalId); 2169 newPart.LocalId);
1495 2170
1496 newPart.DoPhysicsPropertyUpdate(originalPartPa.IsPhysical, true); 2171 newPart.DoPhysicsPropertyUpdate(isphys, true);
1497 } 2172 */
2173 if (userExposed)
2174 newPart.ApplyPhysics((uint)newPart.Flags,newPart.VolumeDetectActive,true);
2175// }
1498 } 2176 }
1499 2177
1500 if (userExposed) 2178 if (userExposed)
1501 { 2179 {
1502 dupe.UpdateParentIDs(); 2180// done above dupe.UpdateParentIDs();
2181
2182 if (dupe.m_rootPart.PhysActor != null)
2183 dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building
2184
1503 dupe.HasGroupChanged = true; 2185 dupe.HasGroupChanged = true;
1504 dupe.AttachToBackup(); 2186 dupe.AttachToBackup();
1505 2187
1506 ScheduleGroupForFullUpdate(); 2188 ScheduleGroupForFullUpdate();
1507 } 2189 }
1508 2190
2191 m_dupeInProgress = false;
1509 return dupe; 2192 return dupe;
1510 } 2193 }
1511 2194
@@ -1517,11 +2200,24 @@ namespace OpenSim.Region.Framework.Scenes
1517 /// <param name="cGroupID"></param> 2200 /// <param name="cGroupID"></param>
1518 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2201 public void CopyRootPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1519 { 2202 {
1520 SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed)); 2203 // SetRootPart(part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, 0, userExposed));
2204 // give newpart a new local ID lettng old part keep same
2205 SceneObjectPart newpart = part.Copy(part.LocalId, OwnerID, GroupID, 0, userExposed);
2206 newpart.LocalId = m_scene.AllocateLocalId();
2207
2208 SetRootPart(newpart);
2209 if (userExposed)
2210 RootPart.Velocity = Vector3.Zero; // In case source is moving
1521 } 2211 }
1522 2212
1523 public void ScriptSetPhysicsStatus(bool usePhysics) 2213 public void ScriptSetPhysicsStatus(bool usePhysics)
1524 { 2214 {
2215 if (usePhysics)
2216 {
2217 if (RootPart.KeyframeMotion != null)
2218 RootPart.KeyframeMotion.Stop();
2219 RootPart.KeyframeMotion = null;
2220 }
1525 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2221 UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect);
1526 } 2222 }
1527 2223
@@ -1569,13 +2265,14 @@ namespace OpenSim.Region.Framework.Scenes
1569 2265
1570 if (pa != null) 2266 if (pa != null)
1571 { 2267 {
1572 pa.AddForce(impulse, true); 2268 // false to be applied as a impulse
2269 pa.AddForce(impulse, false);
1573 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2270 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1574 } 2271 }
1575 } 2272 }
1576 } 2273 }
1577 2274
1578 public void applyAngularImpulse(Vector3 impulse) 2275 public void ApplyAngularImpulse(Vector3 impulse)
1579 { 2276 {
1580 PhysicsActor pa = RootPart.PhysActor; 2277 PhysicsActor pa = RootPart.PhysActor;
1581 2278
@@ -1583,21 +2280,8 @@ namespace OpenSim.Region.Framework.Scenes
1583 { 2280 {
1584 if (!IsAttachment) 2281 if (!IsAttachment)
1585 { 2282 {
1586 pa.AddAngularForce(impulse, true); 2283 // false to be applied as a impulse
1587 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2284 pa.AddAngularForce(impulse, false);
1588 }
1589 }
1590 }
1591
1592 public void setAngularImpulse(Vector3 impulse)
1593 {
1594 PhysicsActor pa = RootPart.PhysActor;
1595
1596 if (pa != null)
1597 {
1598 if (!IsAttachment)
1599 {
1600 pa.Torque = impulse;
1601 m_scene.PhysicsScene.AddPhysicsActorTaint(pa); 2285 m_scene.PhysicsScene.AddPhysicsActorTaint(pa);
1602 } 2286 }
1603 } 2287 }
@@ -1605,20 +2289,10 @@ namespace OpenSim.Region.Framework.Scenes
1605 2289
1606 public Vector3 GetTorque() 2290 public Vector3 GetTorque()
1607 { 2291 {
1608 PhysicsActor pa = RootPart.PhysActor; 2292 return RootPart.Torque;
1609
1610 if (pa != null)
1611 {
1612 if (!IsAttachment)
1613 {
1614 Vector3 torque = pa.Torque;
1615 return torque;
1616 }
1617 }
1618
1619 return Vector3.Zero;
1620 } 2293 }
1621 2294
2295 // This is used by both Double-Click Auto-Pilot and llMoveToTarget() in an attached object
1622 public void moveToTarget(Vector3 target, float tau) 2296 public void moveToTarget(Vector3 target, float tau)
1623 { 2297 {
1624 if (IsAttachment) 2298 if (IsAttachment)
@@ -1650,6 +2324,46 @@ namespace OpenSim.Region.Framework.Scenes
1650 pa.PIDActive = false; 2324 pa.PIDActive = false;
1651 } 2325 }
1652 2326
2327 public void rotLookAt(Quaternion target, float strength, float damping)
2328 {
2329 SceneObjectPart rootpart = m_rootPart;
2330 if (rootpart != null)
2331 {
2332 if (IsAttachment)
2333 {
2334 /*
2335 ScenePresence avatar = m_scene.GetScenePresence(rootpart.AttachedAvatar);
2336 if (avatar != null)
2337 {
2338 Rotate the Av?
2339 } */
2340 }
2341 else
2342 {
2343 if (rootpart.PhysActor != null)
2344 { // APID must be implemented in your physics system for this to function.
2345 rootpart.PhysActor.APIDTarget = new Quaternion(target.X, target.Y, target.Z, target.W);
2346 rootpart.PhysActor.APIDStrength = strength;
2347 rootpart.PhysActor.APIDDamping = damping;
2348 rootpart.PhysActor.APIDActive = true;
2349 }
2350 }
2351 }
2352 }
2353
2354 public void stopLookAt()
2355 {
2356 SceneObjectPart rootpart = m_rootPart;
2357 if (rootpart != null)
2358 {
2359 if (rootpart.PhysActor != null)
2360 { // APID must be implemented in your physics system for this to function.
2361 rootpart.PhysActor.APIDActive = false;
2362 }
2363 }
2364
2365 }
2366
1653 /// <summary> 2367 /// <summary>
1654 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. 2368 /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
1655 /// </summary> 2369 /// </summary>
@@ -1666,7 +2380,7 @@ namespace OpenSim.Region.Framework.Scenes
1666 { 2380 {
1667 pa.PIDHoverHeight = height; 2381 pa.PIDHoverHeight = height;
1668 pa.PIDHoverType = hoverType; 2382 pa.PIDHoverType = hoverType;
1669 pa.PIDTau = tau; 2383 pa.PIDHoverTau = tau;
1670 pa.PIDHoverActive = true; 2384 pa.PIDHoverActive = true;
1671 } 2385 }
1672 else 2386 else
@@ -1706,7 +2420,12 @@ namespace OpenSim.Region.Framework.Scenes
1706 /// <param name="cGroupID"></param> 2420 /// <param name="cGroupID"></param>
1707 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed) 2421 public SceneObjectPart CopyPart(SceneObjectPart part, UUID cAgentID, UUID cGroupID, bool userExposed)
1708 { 2422 {
1709 SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed); 2423 // give new ID to the new part, letting old keep original
2424 // SceneObjectPart newPart = part.Copy(m_scene.AllocateLocalId(), OwnerID, GroupID, m_parts.Count, userExposed);
2425 SceneObjectPart newPart = part.Copy(part.LocalId, OwnerID, GroupID, m_parts.Count, userExposed);
2426 newPart.LocalId = m_scene.AllocateLocalId();
2427 newPart.SetParent(this);
2428
1710 AddPart(newPart); 2429 AddPart(newPart);
1711 2430
1712 SetPartAsNonRoot(newPart); 2431 SetPartAsNonRoot(newPart);
@@ -1835,11 +2554,11 @@ namespace OpenSim.Region.Framework.Scenes
1835 /// Immediately send a full update for this scene object. 2554 /// Immediately send a full update for this scene object.
1836 /// </summary> 2555 /// </summary>
1837 public void SendGroupFullUpdate() 2556 public void SendGroupFullUpdate()
1838 { 2557 {
1839 if (IsDeleted) 2558 if (IsDeleted)
1840 return; 2559 return;
1841 2560
1842// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID); 2561// m_log.DebugFormat("[SOG]: Sending immediate full group update for {0} {1}", Name, UUID);
1843 2562
1844 RootPart.SendFullUpdateToAllClients(); 2563 RootPart.SendFullUpdateToAllClients();
1845 2564
@@ -1973,6 +2692,11 @@ namespace OpenSim.Region.Framework.Scenes
1973 2692
1974 SceneObjectPart linkPart = objectGroup.m_rootPart; 2693 SceneObjectPart linkPart = objectGroup.m_rootPart;
1975 2694
2695 if (m_rootPart.PhysActor != null)
2696 m_rootPart.PhysActor.Building = true;
2697 if (linkPart.PhysActor != null)
2698 linkPart.PhysActor.Building = true;
2699
1976 // physics flags from group to be applied to linked parts 2700 // physics flags from group to be applied to linked parts
1977 bool grpusephys = UsesPhysics; 2701 bool grpusephys = UsesPhysics;
1978 bool grptemporary = IsTemporary; 2702 bool grptemporary = IsTemporary;
@@ -1981,19 +2705,21 @@ namespace OpenSim.Region.Framework.Scenes
1981 Quaternion oldRootRotation = linkPart.RotationOffset; 2705 Quaternion oldRootRotation = linkPart.RotationOffset;
1982 2706
1983 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition; 2707 linkPart.OffsetPosition = linkPart.GroupPosition - AbsolutePosition;
2708
1984 linkPart.ParentID = m_rootPart.LocalId; 2709 linkPart.ParentID = m_rootPart.LocalId;
1985 linkPart.GroupPosition = AbsolutePosition; 2710
1986 Vector3 axPos = linkPart.OffsetPosition; 2711 linkPart.GroupPosition = AbsolutePosition;
1987 2712
2713 Vector3 axPos = linkPart.OffsetPosition;
1988 Quaternion parentRot = m_rootPart.RotationOffset; 2714 Quaternion parentRot = m_rootPart.RotationOffset;
1989 axPos *= Quaternion.Inverse(parentRot); 2715 axPos *= Quaternion.Conjugate(parentRot);
1990
1991 linkPart.OffsetPosition = axPos; 2716 linkPart.OffsetPosition = axPos;
2717
1992 Quaternion oldRot = linkPart.RotationOffset; 2718 Quaternion oldRot = linkPart.RotationOffset;
1993 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2719 Quaternion newRot = Quaternion.Conjugate(parentRot) * oldRot;
1994 linkPart.RotationOffset = newRot; 2720 linkPart.RotationOffset = newRot;
1995 2721
1996 linkPart.ParentID = m_rootPart.LocalId; 2722// linkPart.ParentID = m_rootPart.LocalId; done above
1997 2723
1998 if (m_rootPart.LinkNum == 0) 2724 if (m_rootPart.LinkNum == 0)
1999 m_rootPart.LinkNum = 1; 2725 m_rootPart.LinkNum = 1;
@@ -2021,7 +2747,7 @@ namespace OpenSim.Region.Framework.Scenes
2021 linkPart.CreateSelected = true; 2747 linkPart.CreateSelected = true;
2022 2748
2023 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now 2749 // let physics know preserve part volume dtc messy since UpdatePrimFlags doesn't look to parent changes for now
2024 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive); 2750 linkPart.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (linkPart.Flags & PrimFlags.Phantom) != 0), linkPart.VolumeDetectActive, true);
2025 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 2751 if (linkPart.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2026 { 2752 {
2027 linkPart.PhysActor.link(m_rootPart.PhysActor); 2753 linkPart.PhysActor.link(m_rootPart.PhysActor);
@@ -2029,6 +2755,7 @@ namespace OpenSim.Region.Framework.Scenes
2029 } 2755 }
2030 2756
2031 linkPart.LinkNum = linkNum++; 2757 linkPart.LinkNum = linkNum++;
2758 linkPart.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2032 2759
2033 SceneObjectPart[] ogParts = objectGroup.Parts; 2760 SceneObjectPart[] ogParts = objectGroup.Parts;
2034 Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b) 2761 Array.Sort(ogParts, delegate(SceneObjectPart a, SceneObjectPart b)
@@ -2043,7 +2770,7 @@ namespace OpenSim.Region.Framework.Scenes
2043 { 2770 {
2044 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++); 2771 LinkNonRootPart(part, oldGroupPosition, oldRootRotation, linkNum++);
2045 // let physics know 2772 // let physics know
2046 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive); 2773 part.UpdatePrimFlags(grpusephys, grptemporary, (IsPhantom || (part.Flags & PrimFlags.Phantom) != 0), part.VolumeDetectActive, true);
2047 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical) 2774 if (part.PhysActor != null && m_rootPart.PhysActor != null && m_rootPart.PhysActor.IsPhysical)
2048 { 2775 {
2049 part.PhysActor.link(m_rootPart.PhysActor); 2776 part.PhysActor.link(m_rootPart.PhysActor);
@@ -2058,7 +2785,7 @@ namespace OpenSim.Region.Framework.Scenes
2058 objectGroup.IsDeleted = true; 2785 objectGroup.IsDeleted = true;
2059 2786
2060 objectGroup.m_parts.Clear(); 2787 objectGroup.m_parts.Clear();
2061 2788
2062 // Can't do this yet since backup still makes use of the root part without any synchronization 2789 // Can't do this yet since backup still makes use of the root part without any synchronization
2063// objectGroup.m_rootPart = null; 2790// objectGroup.m_rootPart = null;
2064 2791
@@ -2069,6 +2796,9 @@ namespace OpenSim.Region.Framework.Scenes
2069 // unmoved prims! 2796 // unmoved prims!
2070 ResetChildPrimPhysicsPositions(); 2797 ResetChildPrimPhysicsPositions();
2071 2798
2799 if (m_rootPart.PhysActor != null)
2800 m_rootPart.PhysActor.Building = false;
2801
2072 //HasGroupChanged = true; 2802 //HasGroupChanged = true;
2073 //ScheduleGroupForFullUpdate(); 2803 //ScheduleGroupForFullUpdate();
2074 } 2804 }
@@ -2136,7 +2866,10 @@ namespace OpenSim.Region.Framework.Scenes
2136// m_log.DebugFormat( 2866// m_log.DebugFormat(
2137// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}", 2867// "[SCENE OBJECT GROUP]: Delinking part {0}, {1} from group with root part {2}, {3}",
2138// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID); 2868// linkPart.Name, linkPart.UUID, RootPart.Name, RootPart.UUID);
2139 2869
2870 if (m_rootPart.PhysActor != null)
2871 m_rootPart.PhysActor.Building = true;
2872
2140 linkPart.ClearUndoState(); 2873 linkPart.ClearUndoState();
2141 2874
2142 Quaternion worldRot = linkPart.GetWorldRotation(); 2875 Quaternion worldRot = linkPart.GetWorldRotation();
@@ -2196,6 +2929,14 @@ namespace OpenSim.Region.Framework.Scenes
2196 2929
2197 // When we delete a group, we currently have to force persist to the database if the object id has changed 2930 // When we delete a group, we currently have to force persist to the database if the object id has changed
2198 // (since delete works by deleting all rows which have a given object id) 2931 // (since delete works by deleting all rows which have a given object id)
2932
2933 // this is as it seems to be in sl now
2934 if(linkPart.PhysicsShapeType == (byte)PhysShapeType.none)
2935 linkPart.PhysicsShapeType = linkPart.DefaultPhysicsShapeType(); // root prims can't have type none for now
2936
2937 if (m_rootPart.PhysActor != null)
2938 m_rootPart.PhysActor.Building = false;
2939
2199 objectGroup.HasGroupChangedDueToDelink = true; 2940 objectGroup.HasGroupChangedDueToDelink = true;
2200 2941
2201 return objectGroup; 2942 return objectGroup;
@@ -2207,6 +2948,7 @@ namespace OpenSim.Region.Framework.Scenes
2207 /// <param name="objectGroup"></param> 2948 /// <param name="objectGroup"></param>
2208 public virtual void DetachFromBackup() 2949 public virtual void DetachFromBackup()
2209 { 2950 {
2951 m_scene.SceneGraph.FireDetachFromBackup(this);
2210 if (m_isBackedUp && Scene != null) 2952 if (m_isBackedUp && Scene != null)
2211 m_scene.EventManager.OnBackup -= ProcessBackup; 2953 m_scene.EventManager.OnBackup -= ProcessBackup;
2212 2954
@@ -2225,7 +2967,8 @@ namespace OpenSim.Region.Framework.Scenes
2225 2967
2226 axPos *= parentRot; 2968 axPos *= parentRot;
2227 part.OffsetPosition = axPos; 2969 part.OffsetPosition = axPos;
2228 part.GroupPosition = oldGroupPosition + part.OffsetPosition; 2970 Vector3 newPos = oldGroupPosition + part.OffsetPosition;
2971 part.GroupPosition = newPos;
2229 part.OffsetPosition = Vector3.Zero; 2972 part.OffsetPosition = Vector3.Zero;
2230 part.RotationOffset = worldRot; 2973 part.RotationOffset = worldRot;
2231 2974
@@ -2236,20 +2979,20 @@ namespace OpenSim.Region.Framework.Scenes
2236 2979
2237 part.LinkNum = linkNum; 2980 part.LinkNum = linkNum;
2238 2981
2239 part.OffsetPosition = part.GroupPosition - AbsolutePosition; 2982 part.OffsetPosition = newPos - AbsolutePosition;
2240 2983
2241 Quaternion rootRotation = m_rootPart.RotationOffset; 2984 Quaternion rootRotation = m_rootPart.RotationOffset;
2242 2985
2243 Vector3 pos = part.OffsetPosition; 2986 Vector3 pos = part.OffsetPosition;
2244 pos *= Quaternion.Inverse(rootRotation); 2987 pos *= Quaternion.Conjugate(rootRotation);
2245 part.OffsetPosition = pos; 2988 part.OffsetPosition = pos;
2246 2989
2247 parentRot = m_rootPart.RotationOffset; 2990 parentRot = m_rootPart.RotationOffset;
2248 oldRot = part.RotationOffset; 2991 oldRot = part.RotationOffset;
2249 Quaternion newRot = Quaternion.Inverse(parentRot) * oldRot; 2992 Quaternion newRot = Quaternion.Conjugate(parentRot) * worldRot;
2250 part.RotationOffset = newRot; 2993 part.RotationOffset = newRot;
2251 2994
2252 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect); 2995 part.UpdatePrimFlags(UsesPhysics, IsTemporary, IsPhantom, IsVolumeDetect, false);
2253 } 2996 }
2254 2997
2255 /// <summary> 2998 /// <summary>
@@ -2500,8 +3243,22 @@ namespace OpenSim.Region.Framework.Scenes
2500 } 3243 }
2501 } 3244 }
2502 3245
2503 for (int i = 0; i < parts.Length; i++) 3246 if (parts.Length > 1)
2504 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect); 3247 {
3248 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3249
3250 for (int i = 0; i < parts.Length; i++)
3251 {
3252
3253 if (parts[i].UUID != m_rootPart.UUID)
3254 parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true);
3255 }
3256
3257 if (m_rootPart.PhysActor != null)
3258 m_rootPart.PhysActor.Building = false;
3259 }
3260 else
3261 m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false);
2505 } 3262 }
2506 } 3263 }
2507 3264
@@ -2514,6 +3271,17 @@ namespace OpenSim.Region.Framework.Scenes
2514 } 3271 }
2515 } 3272 }
2516 3273
3274
3275
3276 /// <summary>
3277 /// Gets the number of parts
3278 /// </summary>
3279 /// <returns></returns>
3280 public int GetPartCount()
3281 {
3282 return Parts.Count();
3283 }
3284
2517 /// <summary> 3285 /// <summary>
2518 /// Update the texture entry for this part 3286 /// Update the texture entry for this part
2519 /// </summary> 3287 /// </summary>
@@ -2575,11 +3343,6 @@ namespace OpenSim.Region.Framework.Scenes
2575 /// <param name="scale"></param> 3343 /// <param name="scale"></param>
2576 public void GroupResize(Vector3 scale) 3344 public void GroupResize(Vector3 scale)
2577 { 3345 {
2578// m_log.DebugFormat(
2579// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale);
2580
2581 RootPart.StoreUndoState(true);
2582
2583 scale.X = Math.Min(scale.X, Scene.m_maxNonphys); 3346 scale.X = Math.Min(scale.X, Scene.m_maxNonphys);
2584 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); 3347 scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys);
2585 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); 3348 scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys);
@@ -2606,7 +3369,6 @@ namespace OpenSim.Region.Framework.Scenes
2606 SceneObjectPart obPart = parts[i]; 3369 SceneObjectPart obPart = parts[i];
2607 if (obPart.UUID != m_rootPart.UUID) 3370 if (obPart.UUID != m_rootPart.UUID)
2608 { 3371 {
2609// obPart.IgnoreUndoUpdate = true;
2610 Vector3 oldSize = new Vector3(obPart.Scale); 3372 Vector3 oldSize = new Vector3(obPart.Scale);
2611 3373
2612 float f = 1.0f; 3374 float f = 1.0f;
@@ -2670,8 +3432,6 @@ namespace OpenSim.Region.Framework.Scenes
2670 z *= a; 3432 z *= a;
2671 } 3433 }
2672 } 3434 }
2673
2674// obPart.IgnoreUndoUpdate = false;
2675 } 3435 }
2676 } 3436 }
2677 } 3437 }
@@ -2681,9 +3441,7 @@ namespace OpenSim.Region.Framework.Scenes
2681 prevScale.Y *= y; 3441 prevScale.Y *= y;
2682 prevScale.Z *= z; 3442 prevScale.Z *= z;
2683 3443
2684// RootPart.IgnoreUndoUpdate = true;
2685 RootPart.Resize(prevScale); 3444 RootPart.Resize(prevScale);
2686// RootPart.IgnoreUndoUpdate = false;
2687 3445
2688 parts = m_parts.GetArray(); 3446 parts = m_parts.GetArray();
2689 for (int i = 0; i < parts.Length; i++) 3447 for (int i = 0; i < parts.Length; i++)
@@ -2692,8 +3450,6 @@ namespace OpenSim.Region.Framework.Scenes
2692 3450
2693 if (obPart.UUID != m_rootPart.UUID) 3451 if (obPart.UUID != m_rootPart.UUID)
2694 { 3452 {
2695 obPart.IgnoreUndoUpdate = true;
2696
2697 Vector3 currentpos = new Vector3(obPart.OffsetPosition); 3453 Vector3 currentpos = new Vector3(obPart.OffsetPosition);
2698 currentpos.X *= x; 3454 currentpos.X *= x;
2699 currentpos.Y *= y; 3455 currentpos.Y *= y;
@@ -2706,16 +3462,12 @@ namespace OpenSim.Region.Framework.Scenes
2706 3462
2707 obPart.Resize(newSize); 3463 obPart.Resize(newSize);
2708 obPart.UpdateOffSet(currentpos); 3464 obPart.UpdateOffSet(currentpos);
2709
2710 obPart.IgnoreUndoUpdate = false;
2711 } 3465 }
2712 3466
2713// obPart.IgnoreUndoUpdate = false; 3467 HasGroupChanged = true;
2714// obPart.StoreUndoState(); 3468 m_rootPart.TriggerScriptChangedEvent(Changed.SCALE);
3469 ScheduleGroupForTerseUpdate();
2715 } 3470 }
2716
2717// m_log.DebugFormat(
2718// "[SCENE OBJECT GROUP]: Finished group resizing {0} {1} to {2}", Name, LocalId, RootPart.Scale);
2719 } 3471 }
2720 3472
2721 #endregion 3473 #endregion
@@ -2728,14 +3480,6 @@ namespace OpenSim.Region.Framework.Scenes
2728 /// <param name="pos"></param> 3480 /// <param name="pos"></param>
2729 public void UpdateGroupPosition(Vector3 pos) 3481 public void UpdateGroupPosition(Vector3 pos)
2730 { 3482 {
2731// m_log.DebugFormat("[SCENE OBJECT GROUP]: Updating group position on {0} {1} to {2}", Name, LocalId, pos);
2732
2733 RootPart.StoreUndoState(true);
2734
2735// SceneObjectPart[] parts = m_parts.GetArray();
2736// for (int i = 0; i < parts.Length; i++)
2737// parts[i].StoreUndoState();
2738
2739 if (m_scene.EventManager.TriggerGroupMove(UUID, pos)) 3483 if (m_scene.EventManager.TriggerGroupMove(UUID, pos))
2740 { 3484 {
2741 if (IsAttachment) 3485 if (IsAttachment)
@@ -2768,21 +3512,17 @@ namespace OpenSim.Region.Framework.Scenes
2768 /// </summary> 3512 /// </summary>
2769 /// <param name="pos"></param> 3513 /// <param name="pos"></param>
2770 /// <param name="localID"></param> 3514 /// <param name="localID"></param>
3515 ///
3516
2771 public void UpdateSinglePosition(Vector3 pos, uint localID) 3517 public void UpdateSinglePosition(Vector3 pos, uint localID)
2772 { 3518 {
2773 SceneObjectPart part = GetPart(localID); 3519 SceneObjectPart part = GetPart(localID);
2774 3520
2775// SceneObjectPart[] parts = m_parts.GetArray();
2776// for (int i = 0; i < parts.Length; i++)
2777// parts[i].StoreUndoState();
2778
2779 if (part != null) 3521 if (part != null)
2780 { 3522 {
2781// m_log.DebugFormat( 3523// unlock parts position change
2782// "[SCENE OBJECT GROUP]: Updating single position of {0} {1} to {2}", part.Name, part.LocalId, pos); 3524 if (m_rootPart.PhysActor != null)
2783 3525 m_rootPart.PhysActor.Building = true;
2784 part.StoreUndoState(false);
2785 part.IgnoreUndoUpdate = true;
2786 3526
2787 if (part.UUID == m_rootPart.UUID) 3527 if (part.UUID == m_rootPart.UUID)
2788 { 3528 {
@@ -2793,8 +3533,10 @@ namespace OpenSim.Region.Framework.Scenes
2793 part.UpdateOffSet(pos); 3533 part.UpdateOffSet(pos);
2794 } 3534 }
2795 3535
3536 if (m_rootPart.PhysActor != null)
3537 m_rootPart.PhysActor.Building = false;
3538
2796 HasGroupChanged = true; 3539 HasGroupChanged = true;
2797 part.IgnoreUndoUpdate = false;
2798 } 3540 }
2799 } 3541 }
2800 3542
@@ -2804,13 +3546,7 @@ namespace OpenSim.Region.Framework.Scenes
2804 /// <param name="pos"></param> 3546 /// <param name="pos"></param>
2805 public void UpdateRootPosition(Vector3 pos) 3547 public void UpdateRootPosition(Vector3 pos)
2806 { 3548 {
2807// m_log.DebugFormat( 3549 // needs to be called with phys building true
2808// "[SCENE OBJECT GROUP]: Updating root position of {0} {1} to {2}", Name, LocalId, pos);
2809
2810// SceneObjectPart[] parts = m_parts.GetArray();
2811// for (int i = 0; i < parts.Length; i++)
2812// parts[i].StoreUndoState();
2813
2814 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z); 3550 Vector3 newPos = new Vector3(pos.X, pos.Y, pos.Z);
2815 Vector3 oldPos = 3551 Vector3 oldPos =
2816 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X, 3552 new Vector3(AbsolutePosition.X + m_rootPart.OffsetPosition.X,
@@ -2833,7 +3569,14 @@ namespace OpenSim.Region.Framework.Scenes
2833 AbsolutePosition = newPos; 3569 AbsolutePosition = newPos;
2834 3570
2835 HasGroupChanged = true; 3571 HasGroupChanged = true;
2836 ScheduleGroupForTerseUpdate(); 3572 if (m_rootPart.Undoing)
3573 {
3574 ScheduleGroupForFullUpdate();
3575 }
3576 else
3577 {
3578 ScheduleGroupForTerseUpdate();
3579 }
2837 } 3580 }
2838 3581
2839 #endregion 3582 #endregion
@@ -2846,24 +3589,16 @@ namespace OpenSim.Region.Framework.Scenes
2846 /// <param name="rot"></param> 3589 /// <param name="rot"></param>
2847 public void UpdateGroupRotationR(Quaternion rot) 3590 public void UpdateGroupRotationR(Quaternion rot)
2848 { 3591 {
2849// m_log.DebugFormat(
2850// "[SCENE OBJECT GROUP]: Updating group rotation R of {0} {1} to {2}", Name, LocalId, rot);
2851
2852// SceneObjectPart[] parts = m_parts.GetArray();
2853// for (int i = 0; i < parts.Length; i++)
2854// parts[i].StoreUndoState();
2855
2856 m_rootPart.StoreUndoState(true);
2857
2858 m_rootPart.UpdateRotation(rot); 3592 m_rootPart.UpdateRotation(rot);
2859 3593
3594/* this is done by rootpart RotationOffset set called by UpdateRotation
2860 PhysicsActor actor = m_rootPart.PhysActor; 3595 PhysicsActor actor = m_rootPart.PhysActor;
2861 if (actor != null) 3596 if (actor != null)
2862 { 3597 {
2863 actor.Orientation = m_rootPart.RotationOffset; 3598 actor.Orientation = m_rootPart.RotationOffset;
2864 m_scene.PhysicsScene.AddPhysicsActorTaint(actor); 3599 m_scene.PhysicsScene.AddPhysicsActorTaint(actor);
2865 } 3600 }
2866 3601*/
2867 HasGroupChanged = true; 3602 HasGroupChanged = true;
2868 ScheduleGroupForTerseUpdate(); 3603 ScheduleGroupForTerseUpdate();
2869 } 3604 }
@@ -2875,16 +3610,6 @@ namespace OpenSim.Region.Framework.Scenes
2875 /// <param name="rot"></param> 3610 /// <param name="rot"></param>
2876 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot) 3611 public void UpdateGroupRotationPR(Vector3 pos, Quaternion rot)
2877 { 3612 {
2878// m_log.DebugFormat(
2879// "[SCENE OBJECT GROUP]: Updating group rotation PR of {0} {1} to {2}", Name, LocalId, rot);
2880
2881// SceneObjectPart[] parts = m_parts.GetArray();
2882// for (int i = 0; i < parts.Length; i++)
2883// parts[i].StoreUndoState();
2884
2885 RootPart.StoreUndoState(true);
2886 RootPart.IgnoreUndoUpdate = true;
2887
2888 m_rootPart.UpdateRotation(rot); 3613 m_rootPart.UpdateRotation(rot);
2889 3614
2890 PhysicsActor actor = m_rootPart.PhysActor; 3615 PhysicsActor actor = m_rootPart.PhysActor;
@@ -2898,8 +3623,6 @@ namespace OpenSim.Region.Framework.Scenes
2898 3623
2899 HasGroupChanged = true; 3624 HasGroupChanged = true;
2900 ScheduleGroupForTerseUpdate(); 3625 ScheduleGroupForTerseUpdate();
2901
2902 RootPart.IgnoreUndoUpdate = false;
2903 } 3626 }
2904 3627
2905 /// <summary> 3628 /// <summary>
@@ -2912,13 +3635,11 @@ namespace OpenSim.Region.Framework.Scenes
2912 SceneObjectPart part = GetPart(localID); 3635 SceneObjectPart part = GetPart(localID);
2913 3636
2914 SceneObjectPart[] parts = m_parts.GetArray(); 3637 SceneObjectPart[] parts = m_parts.GetArray();
2915 for (int i = 0; i < parts.Length; i++)
2916 parts[i].StoreUndoState();
2917 3638
2918 if (part != null) 3639 if (part != null)
2919 { 3640 {
2920// m_log.DebugFormat( 3641 if (m_rootPart.PhysActor != null)
2921// "[SCENE OBJECT GROUP]: Updating single rotation of {0} {1} to {2}", part.Name, part.LocalId, rot); 3642 m_rootPart.PhysActor.Building = true;
2922 3643
2923 if (part.UUID == m_rootPart.UUID) 3644 if (part.UUID == m_rootPart.UUID)
2924 { 3645 {
@@ -2928,6 +3649,9 @@ namespace OpenSim.Region.Framework.Scenes
2928 { 3649 {
2929 part.UpdateRotation(rot); 3650 part.UpdateRotation(rot);
2930 } 3651 }
3652
3653 if (m_rootPart.PhysActor != null)
3654 m_rootPart.PhysActor.Building = false;
2931 } 3655 }
2932 } 3656 }
2933 3657
@@ -2941,12 +3665,8 @@ namespace OpenSim.Region.Framework.Scenes
2941 SceneObjectPart part = GetPart(localID); 3665 SceneObjectPart part = GetPart(localID);
2942 if (part != null) 3666 if (part != null)
2943 { 3667 {
2944// m_log.DebugFormat( 3668 if (m_rootPart.PhysActor != null)
2945// "[SCENE OBJECT GROUP]: Updating single position and rotation of {0} {1} to {2}", 3669 m_rootPart.PhysActor.Building = true;
2946// part.Name, part.LocalId, rot);
2947
2948 part.StoreUndoState();
2949 part.IgnoreUndoUpdate = true;
2950 3670
2951 if (part.UUID == m_rootPart.UUID) 3671 if (part.UUID == m_rootPart.UUID)
2952 { 3672 {
@@ -2959,7 +3679,8 @@ namespace OpenSim.Region.Framework.Scenes
2959 part.OffsetPosition = pos; 3679 part.OffsetPosition = pos;
2960 } 3680 }
2961 3681
2962 part.IgnoreUndoUpdate = false; 3682 if (m_rootPart.PhysActor != null)
3683 m_rootPart.PhysActor.Building = false;
2963 } 3684 }
2964 } 3685 }
2965 3686
@@ -2969,15 +3690,12 @@ namespace OpenSim.Region.Framework.Scenes
2969 /// <param name="rot"></param> 3690 /// <param name="rot"></param>
2970 public void UpdateRootRotation(Quaternion rot) 3691 public void UpdateRootRotation(Quaternion rot)
2971 { 3692 {
2972// m_log.DebugFormat( 3693 // needs to be called with phys building true
2973// "[SCENE OBJECT GROUP]: Updating root rotation of {0} {1} to {2}",
2974// Name, LocalId, rot);
2975
2976 Quaternion axRot = rot; 3694 Quaternion axRot = rot;
2977 Quaternion oldParentRot = m_rootPart.RotationOffset; 3695 Quaternion oldParentRot = m_rootPart.RotationOffset;
2978 3696
2979 m_rootPart.StoreUndoState(); 3697 //Don't use UpdateRotation because it schedules an update prematurely
2980 m_rootPart.UpdateRotation(rot); 3698 m_rootPart.RotationOffset = rot;
2981 3699
2982 PhysicsActor pa = m_rootPart.PhysActor; 3700 PhysicsActor pa = m_rootPart.PhysActor;
2983 3701
@@ -2993,35 +3711,145 @@ namespace OpenSim.Region.Framework.Scenes
2993 SceneObjectPart prim = parts[i]; 3711 SceneObjectPart prim = parts[i];
2994 if (prim.UUID != m_rootPart.UUID) 3712 if (prim.UUID != m_rootPart.UUID)
2995 { 3713 {
2996 prim.IgnoreUndoUpdate = true; 3714 Quaternion NewRot = oldParentRot * prim.RotationOffset;
3715 NewRot = Quaternion.Inverse(axRot) * NewRot;
3716 prim.RotationOffset = NewRot;
3717
2997 Vector3 axPos = prim.OffsetPosition; 3718 Vector3 axPos = prim.OffsetPosition;
3719
2998 axPos *= oldParentRot; 3720 axPos *= oldParentRot;
2999 axPos *= Quaternion.Inverse(axRot); 3721 axPos *= Quaternion.Inverse(axRot);
3000 prim.OffsetPosition = axPos; 3722 prim.OffsetPosition = axPos;
3001 Quaternion primsRot = prim.RotationOffset; 3723 }
3002 Quaternion newRot = oldParentRot * primsRot; 3724 }
3003 newRot = Quaternion.Inverse(axRot) * newRot;
3004 prim.RotationOffset = newRot;
3005 prim.ScheduleTerseUpdate();
3006 prim.IgnoreUndoUpdate = false;
3007 }
3008 }
3009
3010// for (int i = 0; i < parts.Length; i++)
3011// {
3012// SceneObjectPart childpart = parts[i];
3013// if (childpart != m_rootPart)
3014// {
3015//// childpart.IgnoreUndoUpdate = false;
3016//// childpart.StoreUndoState();
3017// }
3018// }
3019 3725
3020 m_rootPart.ScheduleTerseUpdate(); 3726 HasGroupChanged = true;
3727 ScheduleGroupForFullUpdate();
3728 }
3021 3729
3022// m_log.DebugFormat( 3730 private enum updatetype :int
3023// "[SCENE OBJECT GROUP]: Updated root rotation of {0} {1} to {2}", 3731 {
3024// Name, LocalId, rot); 3732 none = 0,
3733 partterse = 1,
3734 partfull = 2,
3735 groupterse = 3,
3736 groupfull = 4
3737 }
3738
3739 public void doChangeObject(SceneObjectPart part, ObjectChangeData data)
3740 {
3741 // TODO this still as excessive *.Schedule*Update()s
3742
3743 if (part != null && part.ParentGroup != null)
3744 {
3745 ObjectChangeType change = data.change;
3746 bool togroup = ((change & ObjectChangeType.Group) != 0);
3747 // bool uniform = ((what & ObjectChangeType.UniformScale) != 0); not in use
3748
3749 SceneObjectGroup group = part.ParentGroup;
3750 PhysicsActor pha = group.RootPart.PhysActor;
3751
3752 updatetype updateType = updatetype.none;
3753
3754 if (togroup)
3755 {
3756 // related to group
3757 if ((change & (ObjectChangeType.Rotation | ObjectChangeType.Position)) != 0)
3758 {
3759 if ((change & ObjectChangeType.Rotation) != 0)
3760 {
3761 group.RootPart.UpdateRotation(data.rotation);
3762 updateType = updatetype.none;
3763 }
3764 if ((change & ObjectChangeType.Position) != 0)
3765 {
3766 if (IsAttachment || m_scene.Permissions.CanObjectEntry(group.UUID, false, data.position))
3767 UpdateGroupPosition(data.position);
3768 updateType = updatetype.groupterse;
3769 }
3770 else
3771 // ugly rotation update of all parts
3772 {
3773 group.AbsolutePosition = AbsolutePosition;
3774 }
3775
3776 }
3777 if ((change & ObjectChangeType.Scale) != 0)
3778 {
3779 if (pha != null)
3780 pha.Building = true;
3781
3782 group.GroupResize(data.scale);
3783 updateType = updatetype.none;
3784
3785 if (pha != null)
3786 pha.Building = false;
3787 }
3788 }
3789 else
3790 {
3791 // related to single prim in a link-set ( ie group)
3792 if (pha != null)
3793 pha.Building = true;
3794
3795 // root part is special
3796 // parts offset positions or rotations need to change also
3797
3798 if (part == group.RootPart)
3799 {
3800 if ((change & ObjectChangeType.Rotation) != 0)
3801 group.UpdateRootRotation(data.rotation);
3802 if ((change & ObjectChangeType.Position) != 0)
3803 group.UpdateRootPosition(data.position);
3804 if ((change & ObjectChangeType.Scale) != 0)
3805 part.Resize(data.scale);
3806 }
3807 else
3808 {
3809 if ((change & ObjectChangeType.Position) != 0)
3810 {
3811 part.OffsetPosition = data.position;
3812 updateType = updatetype.partterse;
3813 }
3814 if ((change & ObjectChangeType.Rotation) != 0)
3815 {
3816 part.UpdateRotation(data.rotation);
3817 updateType = updatetype.none;
3818 }
3819 if ((change & ObjectChangeType.Scale) != 0)
3820 {
3821 part.Resize(data.scale);
3822 updateType = updatetype.none;
3823 }
3824 }
3825
3826 if (pha != null)
3827 pha.Building = false;
3828 }
3829
3830 if (updateType != updatetype.none)
3831 {
3832 group.HasGroupChanged = true;
3833
3834 switch (updateType)
3835 {
3836 case updatetype.partterse:
3837 part.ScheduleTerseUpdate();
3838 break;
3839 case updatetype.partfull:
3840 part.ScheduleFullUpdate();
3841 break;
3842 case updatetype.groupterse:
3843 group.ScheduleGroupForTerseUpdate();
3844 break;
3845 case updatetype.groupfull:
3846 group.ScheduleGroupForFullUpdate();
3847 break;
3848 default:
3849 break;
3850 }
3851 }
3852 }
3025 } 3853 }
3026 3854
3027 #endregion 3855 #endregion
@@ -3241,11 +4069,50 @@ namespace OpenSim.Region.Framework.Scenes
3241 } 4069 }
3242 } 4070 }
3243 } 4071 }
3244 4072
4073 public Vector3 GetGeometricCenter()
4074 {
4075 // this is not real geometric center but a average of positions relative to root prim acording to
4076 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
4077 // ignoring tortured prims details since sl also seems to ignore
4078 // so no real use in doing it on physics
4079
4080 Vector3 gc = Vector3.Zero;
4081
4082 int nparts = m_parts.Count;
4083 if (nparts <= 1)
4084 return gc;
4085
4086 SceneObjectPart[] parts = m_parts.GetArray();
4087 nparts = parts.Length; // just in case it changed
4088 if (nparts <= 1)
4089 return gc;
4090
4091 Quaternion parentRot = RootPart.RotationOffset;
4092 Vector3 pPos;
4093
4094 // average all parts positions
4095 for (int i = 0; i < nparts; i++)
4096 {
4097 // do it directly
4098 // gc += parts[i].GetWorldPosition();
4099 if (parts[i] != RootPart)
4100 {
4101 pPos = parts[i].OffsetPosition;
4102 gc += pPos;
4103 }
4104
4105 }
4106 gc /= nparts;
4107
4108 // relative to root:
4109// gc -= AbsolutePosition;
4110 return gc;
4111 }
4112
3245 public float GetMass() 4113 public float GetMass()
3246 { 4114 {
3247 float retmass = 0f; 4115 float retmass = 0f;
3248
3249 SceneObjectPart[] parts = m_parts.GetArray(); 4116 SceneObjectPart[] parts = m_parts.GetArray();
3250 for (int i = 0; i < parts.Length; i++) 4117 for (int i = 0; i < parts.Length; i++)
3251 retmass += parts[i].GetMass(); 4118 retmass += parts[i].GetMass();
@@ -3253,6 +4120,39 @@ namespace OpenSim.Region.Framework.Scenes
3253 return retmass; 4120 return retmass;
3254 } 4121 }
3255 4122
4123 // center of mass of full object
4124 public Vector3 GetCenterOfMass()
4125 {
4126 PhysicsActor pa = RootPart.PhysActor;
4127
4128 if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null)
4129 {
4130 // physics knows better about center of mass of physical prims
4131 Vector3 tmp = pa.CenterOfMass;
4132 return tmp;
4133 }
4134
4135 Vector3 Ptot = Vector3.Zero;
4136 float totmass = 0f;
4137 float m;
4138
4139 SceneObjectPart[] parts = m_parts.GetArray();
4140 for (int i = 0; i < parts.Length; i++)
4141 {
4142 m = parts[i].GetMass();
4143 Ptot += parts[i].GetPartCenterOfMass() * m;
4144 totmass += m;
4145 }
4146
4147 if (totmass == 0)
4148 totmass = 0;
4149 else
4150 totmass = 1 / totmass;
4151 Ptot *= totmass;
4152
4153 return Ptot;
4154 }
4155
3256 /// <summary> 4156 /// <summary>
3257 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that 4157 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that
3258 /// the physics engine can use it. 4158 /// the physics engine can use it.
@@ -3406,6 +4306,14 @@ namespace OpenSim.Region.Framework.Scenes
3406 FromItemID = uuid; 4306 FromItemID = uuid;
3407 } 4307 }
3408 4308
4309 public void ResetOwnerChangeFlag()
4310 {
4311 ForEachPart(delegate(SceneObjectPart part)
4312 {
4313 part.ResetOwnerChangeFlag();
4314 });
4315 }
4316
3409 #endregion 4317 #endregion
3410 } 4318 }
3411} 4319}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 17c7661..bb8d065 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.
@@ -121,7 +122,18 @@ namespace OpenSim.Region.Framework.Scenes
121 /// Denote all sides of the prim 122 /// Denote all sides of the prim
122 /// </value> 123 /// </value>
123 public const int ALL_SIDES = -1; 124 public const int ALL_SIDES = -1;
124 125
126 private const scriptEvents PhysicsNeededSubsEvents = (
127 scriptEvents.collision | scriptEvents.collision_start | scriptEvents.collision_end |
128 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
129 );
130 private const scriptEvents PhyscicsPhantonSubsEvents = (
131 scriptEvents.land_collision | scriptEvents.land_collision_start | scriptEvents.land_collision_end
132 );
133 private const scriptEvents PhyscicsVolumeDtcSubsEvents = (
134 scriptEvents.collision_start | scriptEvents.collision_end
135 );
136
125 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 137 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
126 138
127 /// <value> 139 /// <value>
@@ -176,12 +188,25 @@ namespace OpenSim.Region.Framework.Scenes
176 188
177 public double SoundRadius; 189 public double SoundRadius;
178 190
191
179 public uint TimeStampFull; 192 public uint TimeStampFull;
180 193
181 public uint TimeStampLastActivity; // Will be used for AutoReturn 194 public uint TimeStampLastActivity; // Will be used for AutoReturn
182 195
183 public uint TimeStampTerse; 196 public uint TimeStampTerse;
184 197
198 // The following two are to hold the attachment data
199 // while an object is inworld
200 [XmlIgnore]
201 public byte AttachPoint = 0;
202
203 [XmlIgnore]
204 public Vector3 AttachOffset = Vector3.Zero;
205
206 [XmlIgnore]
207 public Quaternion AttachRotation = Quaternion.Identity;
208
209 [XmlIgnore]
185 public int STATUS_ROTATE_X; 210 public int STATUS_ROTATE_X;
186 211
187 public int STATUS_ROTATE_Y; 212 public int STATUS_ROTATE_Y;
@@ -208,8 +233,7 @@ namespace OpenSim.Region.Framework.Scenes
208 233
209 public Vector3 RotationAxis = Vector3.One; 234 public Vector3 RotationAxis = Vector3.One;
210 235
211 public bool VolumeDetectActive; // XmlIgnore set to avoid problems with persistance until I come to care for this 236 public bool VolumeDetectActive;
212 // Certainly this must be a persistant setting finally
213 237
214 public bool IsWaitingForFirstSpinUpdatePacket; 238 public bool IsWaitingForFirstSpinUpdatePacket;
215 239
@@ -249,10 +273,10 @@ namespace OpenSim.Region.Framework.Scenes
249 private Quaternion m_sitTargetOrientation = Quaternion.Identity; 273 private Quaternion m_sitTargetOrientation = Quaternion.Identity;
250 private Vector3 m_sitTargetPosition; 274 private Vector3 m_sitTargetPosition;
251 private string m_sitAnimation = "SIT"; 275 private string m_sitAnimation = "SIT";
276 private bool m_occupied; // KF if any av is sitting on this prim
252 private string m_text = String.Empty; 277 private string m_text = String.Empty;
253 private string m_touchName = String.Empty; 278 private string m_touchName = String.Empty;
254 private readonly Stack<UndoState> m_undo = new Stack<UndoState>(5); 279 private UndoRedoState m_UndoRedo = null;
255 private readonly Stack<UndoState> m_redo = new Stack<UndoState>(5);
256 280
257 private bool m_passTouches = false; 281 private bool m_passTouches = false;
258 private bool m_passCollisions = false; 282 private bool m_passCollisions = false;
@@ -281,7 +305,19 @@ namespace OpenSim.Region.Framework.Scenes
281 protected Vector3 m_lastAcceleration; 305 protected Vector3 m_lastAcceleration;
282 protected Vector3 m_lastAngularVelocity; 306 protected Vector3 m_lastAngularVelocity;
283 protected int m_lastTerseSent; 307 protected int m_lastTerseSent;
284 308 protected float m_buoyancy = 0.0f;
309 protected Vector3 m_force;
310 protected Vector3 m_torque;
311
312 protected byte m_physicsShapeType = (byte)PhysShapeType.prim;
313 protected float m_density = 1000.0f; // in kg/m^3
314 protected float m_gravitymod = 1.0f;
315 protected float m_friction = 0.6f; // wood
316 protected float m_bounce = 0.5f; // wood
317
318
319 protected bool m_isSelected = false;
320
285 /// <summary> 321 /// <summary>
286 /// Stores media texture data 322 /// Stores media texture data
287 /// </summary> 323 /// </summary>
@@ -293,10 +329,25 @@ namespace OpenSim.Region.Framework.Scenes
293 private Vector3 m_cameraAtOffset; 329 private Vector3 m_cameraAtOffset;
294 private bool m_forceMouselook; 330 private bool m_forceMouselook;
295 331
296 // TODO: Collision sound should have default. 332
333 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
334 private sbyte m_collisionSoundType;
297 private UUID m_collisionSound; 335 private UUID m_collisionSound;
298 private float m_collisionSoundVolume; 336 private float m_collisionSoundVolume;
299 337
338 private int LastColSoundSentTime;
339
340
341 private SOPVehicle m_vehicle = null;
342
343 private KeyframeMotion m_keyframeMotion = null;
344
345 public KeyframeMotion KeyframeMotion
346 {
347 get; set;
348 }
349
350
300 #endregion Fields 351 #endregion Fields
301 352
302// ~SceneObjectPart() 353// ~SceneObjectPart()
@@ -325,6 +376,7 @@ namespace OpenSim.Region.Framework.Scenes
325 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from 376 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
326 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log 377 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
327 m_inventory = new SceneObjectPartInventory(this); 378 m_inventory = new SceneObjectPartInventory(this);
379 LastColSoundSentTime = Util.EnvironmentTickCount();
328 } 380 }
329 381
330 /// <summary> 382 /// <summary>
@@ -339,7 +391,7 @@ namespace OpenSim.Region.Framework.Scenes
339 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 391 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
340 Quaternion rotationOffset, Vector3 offsetPosition) : this() 392 Quaternion rotationOffset, Vector3 offsetPosition) : this()
341 { 393 {
342 m_name = "Primitive"; 394 m_name = "Object";
343 395
344 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 396 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
345 LastOwnerID = CreatorID = OwnerID = ownerID; 397 LastOwnerID = CreatorID = OwnerID = ownerID;
@@ -379,7 +431,7 @@ namespace OpenSim.Region.Framework.Scenes
379 private uint _ownerMask = (uint)PermissionMask.All; 431 private uint _ownerMask = (uint)PermissionMask.All;
380 private uint _groupMask = (uint)PermissionMask.None; 432 private uint _groupMask = (uint)PermissionMask.None;
381 private uint _everyoneMask = (uint)PermissionMask.None; 433 private uint _everyoneMask = (uint)PermissionMask.None;
382 private uint _nextOwnerMask = (uint)PermissionMask.All; 434 private uint _nextOwnerMask = (uint)(PermissionMask.Move | PermissionMask.Modify | PermissionMask.Transfer);
383 private PrimFlags _flags = PrimFlags.None; 435 private PrimFlags _flags = PrimFlags.None;
384 private DateTime m_expires; 436 private DateTime m_expires;
385 private DateTime m_rezzed; 437 private DateTime m_rezzed;
@@ -473,12 +525,16 @@ namespace OpenSim.Region.Framework.Scenes
473 } 525 }
474 526
475 /// <value> 527 /// <value>
476 /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes 528 /// Get the inventory list
477 /// </value> 529 /// </value>
478 public TaskInventoryDictionary TaskInventory 530 public TaskInventoryDictionary TaskInventory
479 { 531 {
480 get { return m_inventory.Items; } 532 get {
481 set { m_inventory.Items = value; } 533 return m_inventory.Items;
534 }
535 set {
536 m_inventory.Items = value;
537 }
482 } 538 }
483 539
484 /// <summary> 540 /// <summary>
@@ -528,20 +584,6 @@ namespace OpenSim.Region.Framework.Scenes
528 } 584 }
529 } 585 }
530 586
531 public byte Material
532 {
533 get { return (byte) m_material; }
534 set
535 {
536 m_material = (Material)value;
537
538 PhysicsActor pa = PhysActor;
539
540 if (pa != null)
541 pa.SetMaterial((int)value);
542 }
543 }
544
545 [XmlIgnore] 587 [XmlIgnore]
546 public bool PassTouches 588 public bool PassTouches
547 { 589 {
@@ -567,6 +609,18 @@ namespace OpenSim.Region.Framework.Scenes
567 } 609 }
568 } 610 }
569 611
612 public bool IsSelected
613 {
614 get { return m_isSelected; }
615 set
616 {
617 m_isSelected = value;
618 if (ParentGroup != null)
619 ParentGroup.PartSelectChanged(value);
620 }
621 }
622
623
570 public Dictionary<int, string> CollisionFilter 624 public Dictionary<int, string> CollisionFilter
571 { 625 {
572 get { return m_CollisionFilter; } 626 get { return m_CollisionFilter; }
@@ -635,14 +689,12 @@ namespace OpenSim.Region.Framework.Scenes
635 set { m_LoopSoundSlavePrims = value; } 689 set { m_LoopSoundSlavePrims = value; }
636 } 690 }
637 691
638
639 public Byte[] TextureAnimation 692 public Byte[] TextureAnimation
640 { 693 {
641 get { return m_TextureAnimation; } 694 get { return m_TextureAnimation; }
642 set { m_TextureAnimation = value; } 695 set { m_TextureAnimation = value; }
643 } 696 }
644 697
645
646 public Byte[] ParticleSystem 698 public Byte[] ParticleSystem
647 { 699 {
648 get { return m_particleSystem; } 700 get { return m_particleSystem; }
@@ -679,8 +731,12 @@ namespace OpenSim.Region.Framework.Scenes
679 { 731 {
680 // If this is a linkset, we don't want the physics engine mucking up our group position here. 732 // If this is a linkset, we don't want the physics engine mucking up our group position here.
681 PhysicsActor actor = PhysActor; 733 PhysicsActor actor = PhysActor;
682 if (actor != null && ParentID == 0) 734 if (ParentID == 0)
683 m_groupPosition = actor.Position; 735 {
736 if (actor != null)
737 m_groupPosition = actor.Position;
738 return m_groupPosition;
739 }
684 740
685 if (ParentGroup.IsAttachment) 741 if (ParentGroup.IsAttachment)
686 { 742 {
@@ -689,12 +745,14 @@ namespace OpenSim.Region.Framework.Scenes
689 return sp.AbsolutePosition; 745 return sp.AbsolutePosition;
690 } 746 }
691 747
748 // use root prim's group position. Physics may have updated it
749 if (ParentGroup.RootPart != this)
750 m_groupPosition = ParentGroup.RootPart.GroupPosition;
692 return m_groupPosition; 751 return m_groupPosition;
693 } 752 }
694 set 753 set
695 { 754 {
696 m_groupPosition = value; 755 m_groupPosition = value;
697
698 PhysicsActor actor = PhysActor; 756 PhysicsActor actor = PhysActor;
699 if (actor != null) 757 if (actor != null)
700 { 758 {
@@ -720,16 +778,6 @@ namespace OpenSim.Region.Framework.Scenes
720 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); 778 m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message);
721 } 779 }
722 } 780 }
723
724 // TODO if we decide to do sitting in a more SL compatible way (multiple avatars per prim), this has to be fixed, too
725 if (SitTargetAvatar != UUID.Zero)
726 {
727 ScenePresence avatar;
728 if (ParentGroup.Scene.TryGetScenePresence(SitTargetAvatar, out avatar))
729 {
730 avatar.ParentPosition = GetWorldPosition();
731 }
732 }
733 } 781 }
734 } 782 }
735 783
@@ -738,7 +786,7 @@ namespace OpenSim.Region.Framework.Scenes
738 get { return m_offsetPosition; } 786 get { return m_offsetPosition; }
739 set 787 set
740 { 788 {
741// StoreUndoState(); 789 Vector3 oldpos = m_offsetPosition;
742 m_offsetPosition = value; 790 m_offsetPosition = value;
743 791
744 if (ParentGroup != null && !ParentGroup.IsDeleted) 792 if (ParentGroup != null && !ParentGroup.IsDeleted)
@@ -753,7 +801,22 @@ namespace OpenSim.Region.Framework.Scenes
753 if (ParentGroup.Scene != null) 801 if (ParentGroup.Scene != null)
754 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor); 802 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(actor);
755 } 803 }
804
805 if (!m_parentGroup.m_dupeInProgress)
806 {
807 List<ScenePresence> avs = ParentGroup.GetLinkedAvatars();
808 foreach (ScenePresence av in avs)
809 {
810 if (av.ParentID == m_localId)
811 {
812 Vector3 offset = (m_offsetPosition - oldpos);
813 av.AbsolutePosition += offset;
814 av.SendAvatarDataToAllAgents();
815 }
816 }
817 }
756 } 818 }
819 TriggerScriptChangedEvent(Changed.POSITION);
757 } 820 }
758 } 821 }
759 822
@@ -802,7 +865,7 @@ namespace OpenSim.Region.Framework.Scenes
802 865
803 set 866 set
804 { 867 {
805 StoreUndoState(); 868// StoreUndoState();
806 m_rotationOffset = value; 869 m_rotationOffset = value;
807 870
808 PhysicsActor actor = PhysActor; 871 PhysicsActor actor = PhysActor;
@@ -890,7 +953,7 @@ namespace OpenSim.Region.Framework.Scenes
890 get 953 get
891 { 954 {
892 PhysicsActor actor = PhysActor; 955 PhysicsActor actor = PhysActor;
893 if ((actor != null) && actor.IsPhysical) 956 if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this)
894 { 957 {
895 m_angularVelocity = actor.RotationalVelocity; 958 m_angularVelocity = actor.RotationalVelocity;
896 } 959 }
@@ -902,7 +965,16 @@ namespace OpenSim.Region.Framework.Scenes
902 /// <summary></summary> 965 /// <summary></summary>
903 public Vector3 Acceleration 966 public Vector3 Acceleration
904 { 967 {
905 get { return m_acceleration; } 968 get
969 {
970 PhysicsActor actor = PhysActor;
971 if (actor != null)
972 {
973 m_acceleration = actor.Acceleration;
974 }
975 return m_acceleration;
976 }
977
906 set { m_acceleration = value; } 978 set { m_acceleration = value; }
907 } 979 }
908 980
@@ -970,7 +1042,10 @@ namespace OpenSim.Region.Framework.Scenes
970 public PrimitiveBaseShape Shape 1042 public PrimitiveBaseShape Shape
971 { 1043 {
972 get { return m_shape; } 1044 get { return m_shape; }
973 set { m_shape = value;} 1045 set
1046 {
1047 m_shape = value;
1048 }
974 } 1049 }
975 1050
976 /// <summary> 1051 /// <summary>
@@ -983,7 +1058,6 @@ namespace OpenSim.Region.Framework.Scenes
983 { 1058 {
984 if (m_shape != null) 1059 if (m_shape != null)
985 { 1060 {
986 StoreUndoState();
987 1061
988 m_shape.Scale = value; 1062 m_shape.Scale = value;
989 1063
@@ -1010,6 +1084,7 @@ namespace OpenSim.Region.Framework.Scenes
1010 } 1084 }
1011 1085
1012 public UpdateRequired UpdateFlag { get; set; } 1086 public UpdateRequired UpdateFlag { get; set; }
1087 public bool UpdatePhysRequired { get; set; }
1013 1088
1014 /// <summary> 1089 /// <summary>
1015 /// Used for media on a prim. 1090 /// Used for media on a prim.
@@ -1050,10 +1125,7 @@ namespace OpenSim.Region.Framework.Scenes
1050 { 1125 {
1051 get 1126 get
1052 { 1127 {
1053 if (ParentGroup.IsAttachment) 1128 return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset);
1054 return GroupPosition;
1055
1056 return m_offsetPosition + m_groupPosition;
1057 } 1129 }
1058 } 1130 }
1059 1131
@@ -1231,6 +1303,13 @@ namespace OpenSim.Region.Framework.Scenes
1231 _flags = value; 1303 _flags = value;
1232 } 1304 }
1233 } 1305 }
1306
1307 [XmlIgnore]
1308 public bool IsOccupied // KF If an av is sittingon this prim
1309 {
1310 get { return m_occupied; }
1311 set { m_occupied = value; }
1312 }
1234 1313
1235 /// <summary> 1314 /// <summary>
1236 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero 1315 /// ID of the avatar that is sat on us. If there is no such avatar then is UUID.Zero
@@ -1274,12 +1353,41 @@ namespace OpenSim.Region.Framework.Scenes
1274 set { m_sitAnimation = value; } 1353 set { m_sitAnimation = value; }
1275 } 1354 }
1276 1355
1356 public UUID invalidCollisionSoundUUID = new UUID("ffffffff-ffff-ffff-ffff-ffffffffffff");
1357
1358 // 0 for default collision sounds, -1 for script disabled sound 1 for script defined sound
1359 // runtime thing.. do not persist
1360 [XmlIgnore]
1361 public sbyte CollisionSoundType
1362 {
1363 get
1364 {
1365 return m_collisionSoundType;
1366 }
1367 set
1368 {
1369 m_collisionSoundType = value;
1370 if (value == -1)
1371 m_collisionSound = invalidCollisionSoundUUID;
1372 else if (value == 0)
1373 m_collisionSound = UUID.Zero;
1374 }
1375 }
1376
1277 public UUID CollisionSound 1377 public UUID CollisionSound
1278 { 1378 {
1279 get { return m_collisionSound; } 1379 get { return m_collisionSound; }
1280 set 1380 set
1281 { 1381 {
1282 m_collisionSound = value; 1382 m_collisionSound = value;
1383
1384 if (value == invalidCollisionSoundUUID)
1385 m_collisionSoundType = -1;
1386 else if (value == UUID.Zero)
1387 m_collisionSoundType = 0;
1388 else
1389 m_collisionSoundType = 1;
1390
1283 aggregateScriptEvents(); 1391 aggregateScriptEvents();
1284 } 1392 }
1285 } 1393 }
@@ -1290,6 +1398,319 @@ namespace OpenSim.Region.Framework.Scenes
1290 set { m_collisionSoundVolume = value; } 1398 set { m_collisionSoundVolume = value; }
1291 } 1399 }
1292 1400
1401 public float Buoyancy
1402 {
1403 get
1404 {
1405 if (ParentGroup.RootPart == this)
1406 return m_buoyancy;
1407
1408 return ParentGroup.RootPart.Buoyancy;
1409 }
1410 set
1411 {
1412 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1413 {
1414 ParentGroup.RootPart.Buoyancy = value;
1415 return;
1416 }
1417 m_buoyancy = value;
1418 if (PhysActor != null)
1419 PhysActor.Buoyancy = value;
1420 }
1421 }
1422
1423 public Vector3 Force
1424 {
1425 get
1426 {
1427 if (ParentGroup.RootPart == this)
1428 return m_force;
1429
1430 return ParentGroup.RootPart.Force;
1431 }
1432
1433 set
1434 {
1435 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1436 {
1437 ParentGroup.RootPart.Force = value;
1438 return;
1439 }
1440 m_force = value;
1441 if (PhysActor != null)
1442 PhysActor.Force = value;
1443 }
1444 }
1445
1446 public Vector3 Torque
1447 {
1448 get
1449 {
1450 if (ParentGroup.RootPart == this)
1451 return m_torque;
1452
1453 return ParentGroup.RootPart.Torque;
1454 }
1455
1456 set
1457 {
1458 if (ParentGroup != null && ParentGroup.RootPart != null && ParentGroup.RootPart != this)
1459 {
1460 ParentGroup.RootPart.Torque = value;
1461 return;
1462 }
1463 m_torque = value;
1464 if (PhysActor != null)
1465 PhysActor.Torque = value;
1466 }
1467 }
1468
1469 public byte Material
1470 {
1471 get { return (byte)m_material; }
1472 set
1473 {
1474 if (value >= 0 && value <= (byte)SOPMaterialData.MaxMaterial)
1475 {
1476 bool update = false;
1477
1478 if (m_material != (Material)value)
1479 {
1480 update = true;
1481 m_material = (Material)value;
1482 }
1483
1484 if (m_friction != SOPMaterialData.friction(m_material))
1485 {
1486 update = true;
1487 m_friction = SOPMaterialData.friction(m_material);
1488 }
1489
1490 if (m_bounce != SOPMaterialData.bounce(m_material))
1491 {
1492 update = true;
1493 m_bounce = SOPMaterialData.bounce(m_material);
1494 }
1495
1496 if (update)
1497 {
1498 if (PhysActor != null)
1499 {
1500 PhysActor.SetMaterial((int)value);
1501 }
1502 if(ParentGroup != null)
1503 ParentGroup.HasGroupChanged = true;
1504 ScheduleFullUpdateIfNone();
1505 UpdatePhysRequired = true;
1506 }
1507 }
1508 }
1509 }
1510
1511 // not a propriety to move to methods place later
1512 private bool HasMesh()
1513 {
1514 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1515 return true;
1516 return false;
1517 }
1518
1519 // not a propriety to move to methods place later
1520 public byte DefaultPhysicsShapeType()
1521 {
1522 byte type;
1523
1524 if (Shape != null && (Shape.SculptType == (byte)SculptType.Mesh))
1525 type = (byte)PhysShapeType.convex;
1526 else
1527 type = (byte)PhysShapeType.prim;
1528
1529 return type;
1530 }
1531
1532 [XmlIgnore]
1533 public bool UsesComplexCost
1534 {
1535 get
1536 {
1537 byte pst = PhysicsShapeType;
1538 if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh())
1539 return true;
1540 return false;
1541 }
1542 }
1543
1544 [XmlIgnore]
1545 public float PhysicsCost
1546 {
1547 get
1548 {
1549 if(PhysicsShapeType == (byte)PhysShapeType.none)
1550 return 0;
1551
1552 float cost = 0.1f;
1553 if (PhysActor != null)
1554// cost += PhysActor.Cost;
1555
1556 if ((Flags & PrimFlags.Physics) != 0)
1557 cost *= (1.0f + 0.01333f * Scale.LengthSquared()); // 0.01333 == 0.04/3
1558 return cost;
1559 }
1560 }
1561
1562 [XmlIgnore]
1563 public float StreamingCost
1564 {
1565 get
1566 {
1567
1568
1569 return 0.1f;
1570 }
1571 }
1572
1573 [XmlIgnore]
1574 public float SimulationCost
1575 {
1576 get
1577 {
1578 // ignoring scripts. Don't like considering them for this
1579 if((Flags & PrimFlags.Physics) != 0)
1580 return 1.0f;
1581
1582 return 0.5f;
1583 }
1584 }
1585
1586 public byte PhysicsShapeType
1587 {
1588 get { return m_physicsShapeType; }
1589 set
1590 {
1591 byte oldv = m_physicsShapeType;
1592
1593 if (value >= 0 && value <= (byte)PhysShapeType.convex)
1594 {
1595 if (value == (byte)PhysShapeType.none && ParentGroup != null && ParentGroup.RootPart == this)
1596 m_physicsShapeType = DefaultPhysicsShapeType();
1597 else
1598 m_physicsShapeType = value;
1599 }
1600 else
1601 m_physicsShapeType = DefaultPhysicsShapeType();
1602
1603 if (m_physicsShapeType != oldv && ParentGroup != null)
1604 {
1605 if (m_physicsShapeType == (byte)PhysShapeType.none)
1606 {
1607 if (PhysActor != null)
1608 {
1609 Velocity = new Vector3(0, 0, 0);
1610 Acceleration = new Vector3(0, 0, 0);
1611 if (ParentGroup.RootPart == this)
1612 AngularVelocity = new Vector3(0, 0, 0);
1613 ParentGroup.Scene.RemovePhysicalPrim(1);
1614 RemoveFromPhysics();
1615 }
1616 }
1617 else if (PhysActor == null)
1618 {
1619 ApplyPhysics((uint)Flags, VolumeDetectActive, false);
1620 UpdatePhysicsSubscribedEvents();
1621 }
1622 else
1623 {
1624 PhysActor.PhysicsShapeType = m_physicsShapeType;
1625 if (Shape.SculptEntry)
1626 CheckSculptAndLoad();
1627 }
1628
1629 if (ParentGroup != null)
1630 ParentGroup.HasGroupChanged = true;
1631 }
1632
1633 if (m_physicsShapeType != value)
1634 {
1635 UpdatePhysRequired = true;
1636 }
1637 }
1638 }
1639
1640 public float Density // in kg/m^3
1641 {
1642 get { return m_density; }
1643 set
1644 {
1645 if (value >=1 && value <= 22587.0)
1646 {
1647 m_density = value;
1648 UpdatePhysRequired = true;
1649 }
1650
1651 ScheduleFullUpdateIfNone();
1652
1653 if (ParentGroup != null)
1654 ParentGroup.HasGroupChanged = true;
1655 }
1656 }
1657
1658 public float GravityModifier
1659 {
1660 get { return m_gravitymod; }
1661 set
1662 {
1663 if( value >= -1 && value <=28.0f)
1664 {
1665 m_gravitymod = value;
1666 UpdatePhysRequired = true;
1667 }
1668
1669 ScheduleFullUpdateIfNone();
1670
1671 if (ParentGroup != null)
1672 ParentGroup.HasGroupChanged = true;
1673
1674 }
1675 }
1676
1677 public float Friction
1678 {
1679 get { return m_friction; }
1680 set
1681 {
1682 if (value >= 0 && value <= 255.0f)
1683 {
1684 m_friction = value;
1685 UpdatePhysRequired = true;
1686 }
1687
1688 ScheduleFullUpdateIfNone();
1689
1690 if (ParentGroup != null)
1691 ParentGroup.HasGroupChanged = true;
1692 }
1693 }
1694
1695 public float Bounciness
1696 {
1697 get { return m_bounce; }
1698 set
1699 {
1700 if (value >= 0 && value <= 1.0f)
1701 {
1702 m_bounce = value;
1703 UpdatePhysRequired = true;
1704 }
1705
1706 ScheduleFullUpdateIfNone();
1707
1708 if (ParentGroup != null)
1709 ParentGroup.HasGroupChanged = true;
1710 }
1711 }
1712
1713
1293 #endregion Public Properties with only Get 1714 #endregion Public Properties with only Get
1294 1715
1295 private uint ApplyMask(uint val, bool set, uint mask) 1716 private uint ApplyMask(uint val, bool set, uint mask)
@@ -1455,7 +1876,7 @@ namespace OpenSim.Region.Framework.Scenes
1455 impulse = newimpulse; 1876 impulse = newimpulse;
1456 } 1877 }
1457 1878
1458 ParentGroup.applyAngularImpulse(impulse); 1879 ParentGroup.ApplyAngularImpulse(impulse);
1459 } 1880 }
1460 1881
1461 /// <summary> 1882 /// <summary>
@@ -1465,20 +1886,24 @@ namespace OpenSim.Region.Framework.Scenes
1465 /// </summary> 1886 /// </summary>
1466 /// <param name="impulsei">Vector force</param> 1887 /// <param name="impulsei">Vector force</param>
1467 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param> 1888 /// <param name="localGlobalTF">true for the local frame, false for the global frame</param>
1468 public void SetAngularImpulse(Vector3 impulsei, bool localGlobalTF) 1889
1890 // this is actualy Set Torque.. keeping naming so not to edit lslapi also
1891 public void SetAngularImpulse(Vector3 torquei, bool localGlobalTF)
1469 { 1892 {
1470 Vector3 impulse = impulsei; 1893 Vector3 torque = torquei;
1471 1894
1472 if (localGlobalTF) 1895 if (localGlobalTF)
1473 { 1896 {
1897/*
1474 Quaternion grot = GetWorldRotation(); 1898 Quaternion grot = GetWorldRotation();
1475 Quaternion AXgrot = grot; 1899 Quaternion AXgrot = grot;
1476 Vector3 AXimpulsei = impulsei; 1900 Vector3 AXimpulsei = impulsei;
1477 Vector3 newimpulse = AXimpulsei * AXgrot; 1901 Vector3 newimpulse = AXimpulsei * AXgrot;
1478 impulse = newimpulse; 1902 */
1903 torque *= GetWorldRotation();
1479 } 1904 }
1480 1905
1481 ParentGroup.setAngularImpulse(impulse); 1906 Torque = torque;
1482 } 1907 }
1483 1908
1484 /// <summary> 1909 /// <summary>
@@ -1486,17 +1911,23 @@ namespace OpenSim.Region.Framework.Scenes
1486 /// </summary> 1911 /// </summary>
1487 /// <param name="rootObjectFlags"></param> 1912 /// <param name="rootObjectFlags"></param>
1488 /// <param name="VolumeDetectActive"></param> 1913 /// <param name="VolumeDetectActive"></param>
1489 public void ApplyPhysics(uint rootObjectFlags, bool VolumeDetectActive) 1914 /// <param name="building"></param>
1915
1916 public void ApplyPhysics(uint _ObjectFlags, bool _VolumeDetectActive, bool building)
1490 { 1917 {
1918 VolumeDetectActive = _VolumeDetectActive;
1919
1491 if (!ParentGroup.Scene.CollidablePrims) 1920 if (!ParentGroup.Scene.CollidablePrims)
1492 return; 1921 return;
1493 1922
1494// m_log.DebugFormat( 1923 if (PhysicsShapeType == (byte)PhysShapeType.none)
1495// "[SCENE OBJECT PART]: Applying physics to {0} {1}, m_physicalPrim {2}", 1924 return;
1496// Name, LocalId, UUID, m_physicalPrim); 1925
1926 bool isPhysical = (_ObjectFlags & (uint) PrimFlags.Physics) != 0;
1927 bool isPhantom = (_ObjectFlags & (uint)PrimFlags.Phantom) != 0;
1497 1928
1498 bool isPhysical = (rootObjectFlags & (uint) PrimFlags.Physics) != 0; 1929 if (_VolumeDetectActive)
1499 bool isPhantom = (rootObjectFlags & (uint) PrimFlags.Phantom) != 0; 1930 isPhantom = true;
1500 1931
1501 if (IsJoint()) 1932 if (IsJoint())
1502 { 1933 {
@@ -1504,22 +1935,14 @@ namespace OpenSim.Region.Framework.Scenes
1504 } 1935 }
1505 else 1936 else
1506 { 1937 {
1507 // Special case for VolumeDetection: If VolumeDetection is set, the phantom flag is locally ignored 1938 if ((!isPhantom || isPhysical || _VolumeDetectActive) && !ParentGroup.IsAttachment
1508 if (VolumeDetectActive) 1939 && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1509 isPhantom = false;
1510
1511 // 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
1512 // or flexible
1513 if (!isPhantom && !ParentGroup.IsAttachment && !(Shape.PathCurve == (byte)Extrusion.Flexible))
1514 { 1940 {
1515 // Added clarification.. since A rigid body is an object that you can kick around, etc. 1941 AddToPhysics(isPhysical, isPhantom, building, isPhysical);
1516 bool rigidBody = isPhysical && !isPhantom; 1942 UpdatePhysicsSubscribedEvents(); // not sure if appliable here
1517
1518 PhysicsActor pa = AddToPhysics(rigidBody);
1519
1520 if (pa != null)
1521 pa.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
1522 } 1943 }
1944 else
1945 PhysActor = null; // just to be sure
1523 } 1946 }
1524 } 1947 }
1525 1948
@@ -1571,6 +1994,12 @@ namespace OpenSim.Region.Framework.Scenes
1571 dupe.Category = Category; 1994 dupe.Category = Category;
1572 dupe.m_rezzed = m_rezzed; 1995 dupe.m_rezzed = m_rezzed;
1573 1996
1997 dupe.m_UndoRedo = null;
1998 dupe.m_isSelected = false;
1999
2000 dupe.IgnoreUndoUpdate = false;
2001 dupe.Undoing = false;
2002
1574 dupe.m_inventory = new SceneObjectPartInventory(dupe); 2003 dupe.m_inventory = new SceneObjectPartInventory(dupe);
1575 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone(); 2004 dupe.m_inventory.Items = (TaskInventoryDictionary)m_inventory.Items.Clone();
1576 2005
@@ -1586,6 +2015,7 @@ namespace OpenSim.Region.Framework.Scenes
1586 2015
1587 // Move afterwards ResetIDs as it clears the localID 2016 // Move afterwards ResetIDs as it clears the localID
1588 dupe.LocalId = localID; 2017 dupe.LocalId = localID;
2018
1589 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 2019 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1590 dupe.LastOwnerID = OwnerID; 2020 dupe.LastOwnerID = OwnerID;
1591 2021
@@ -1603,8 +2033,12 @@ namespace OpenSim.Region.Framework.Scenes
1603 2033
1604 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0); 2034 bool UsePhysics = ((dupe.Flags & PrimFlags.Physics) != 0);
1605 dupe.DoPhysicsPropertyUpdate(UsePhysics, true); 2035 dupe.DoPhysicsPropertyUpdate(UsePhysics, true);
2036// dupe.UpdatePhysicsSubscribedEvents(); // not sure...
1606 } 2037 }
1607 2038
2039 if (dupe.PhysActor != null)
2040 dupe.PhysActor.LocalID = localID;
2041
1608 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed); 2042 ParentGroup.Scene.EventManager.TriggerOnSceneObjectPartCopy(dupe, this, userExposed);
1609 2043
1610// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID); 2044// m_log.DebugFormat("[SCENE OBJECT PART]: Clone of {0} {1} finished", Name, UUID);
@@ -1724,6 +2158,7 @@ namespace OpenSim.Region.Framework.Scenes
1724 2158
1725 /// <summary> 2159 /// <summary>
1726 /// Do a physics propery update for this part. 2160 /// Do a physics propery update for this part.
2161 /// now also updates phantom and volume detector
1727 /// </summary> 2162 /// </summary>
1728 /// <param name="UsePhysics"></param> 2163 /// <param name="UsePhysics"></param>
1729 /// <param name="isNew"></param> 2164 /// <param name="isNew"></param>
@@ -1749,61 +2184,69 @@ namespace OpenSim.Region.Framework.Scenes
1749 { 2184 {
1750 if (pa.IsPhysical) // implies UsePhysics==false for this block 2185 if (pa.IsPhysical) // implies UsePhysics==false for this block
1751 { 2186 {
1752 if (!isNew) 2187 if (!isNew) // implies UsePhysics==false for this block
2188 {
1753 ParentGroup.Scene.RemovePhysicalPrim(1); 2189 ParentGroup.Scene.RemovePhysicalPrim(1);
1754 2190
1755 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate; 2191 Velocity = new Vector3(0, 0, 0);
1756 pa.OnOutOfBounds -= PhysicsOutOfBounds; 2192 Acceleration = new Vector3(0, 0, 0);
1757 pa.delink(); 2193 if (ParentGroup.RootPart == this)
2194 AngularVelocity = new Vector3(0, 0, 0);
1758 2195
1759 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints && (!isNew)) 2196 if (pa.Phantom && !VolumeDetectActive)
1760 { 2197 {
1761 // destroy all joints connected to this now deactivated body 2198 RemoveFromPhysics();
1762 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa); 2199 return;
1763 } 2200 }
1764 2201
1765 // stop client-side interpolation of all joint proxy objects that have just been deleted 2202 pa.IsPhysical = UsePhysics;
1766 // this is done because RemoveAllJointsConnectedToActor invokes the OnJointDeactivated callback, 2203 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
1767 // which stops client-side interpolation of deactivated joint proxy objects. 2204 pa.OnOutOfBounds -= PhysicsOutOfBounds;
2205 pa.delink();
2206 if (ParentGroup.Scene.PhysicsScene.SupportsNINJAJoints)
2207 {
2208 // destroy all joints connected to this now deactivated body
2209 ParentGroup.Scene.PhysicsScene.RemoveAllJointsConnectedToActorThreadLocked(pa);
2210 }
2211 }
1768 } 2212 }
1769 2213
1770 if (!UsePhysics && !isNew) 2214 if (pa.IsPhysical != UsePhysics)
1771 { 2215 pa.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 2216
1781 pa.IsPhysical = UsePhysics; 2217 if (UsePhysics)
2218 {
2219 if (ParentGroup.RootPart.KeyframeMotion != null)
2220 ParentGroup.RootPart.KeyframeMotion.Stop();
2221 ParentGroup.RootPart.KeyframeMotion = null;
2222 ParentGroup.Scene.AddPhysicalPrim(1);
1782 2223
1783 // If we're not what we're supposed to be in the physics scene, recreate ourselves. 2224 PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
1784 //m_parentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 2225 PhysActor.OnOutOfBounds += PhysicsOutOfBounds;
1785 /// that's not wholesome. Had to make Scene public
1786 //PhysActor = null;
1787 2226
1788 if ((Flags & PrimFlags.Phantom) == 0) 2227 if (ParentID != 0 && ParentID != LocalId)
1789 {
1790 if (UsePhysics)
1791 { 2228 {
1792 ParentGroup.Scene.AddPhysicalPrim(1); 2229 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
1793 2230
1794 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; 2231 if (parentPa != null)
1795 pa.OnOutOfBounds += PhysicsOutOfBounds;
1796 if (ParentID != 0 && ParentID != LocalId)
1797 { 2232 {
1798 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; 2233 pa.link(parentPa);
1799
1800 if (parentPa != null)
1801 {
1802 pa.link(parentPa);
1803 }
1804 } 2234 }
1805 } 2235 }
1806 } 2236 }
2237 }
2238
2239 bool phan = ((Flags & PrimFlags.Phantom) != 0);
2240 if (pa.Phantom != phan)
2241 pa.Phantom = phan;
2242
2243// some engines dont' have this check still
2244// if (VolumeDetectActive != pa.IsVolumeDtc)
2245 {
2246 if (VolumeDetectActive)
2247 pa.SetVolumeDetect(1);
2248 else
2249 pa.SetVolumeDetect(0);
1807 } 2250 }
1808 2251
1809 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the 2252 // If this part is a sculpt then delay the physics update until we've asynchronously loaded the
@@ -1922,12 +2365,26 @@ namespace OpenSim.Region.Framework.Scenes
1922 2365
1923 public Vector3 GetGeometricCenter() 2366 public Vector3 GetGeometricCenter()
1924 { 2367 {
1925 PhysicsActor pa = PhysActor; 2368 // this is not real geometric center but a average of positions relative to root prim acording to
1926 2369 // http://wiki.secondlife.com/wiki/llGetGeometricCenter
1927 if (pa != null) 2370 // ignoring tortured prims details since sl also seems to ignore
1928 return new Vector3(pa.CenterOfMass.X, pa.CenterOfMass.Y, pa.CenterOfMass.Z); 2371 // so no real use in doing it on physics
1929 else 2372 if (ParentGroup.IsDeleted)
1930 return new Vector3(0, 0, 0); 2373 return new Vector3(0, 0, 0);
2374
2375 return ParentGroup.GetGeometricCenter();
2376
2377 /*
2378 PhysicsActor pa = PhysActor;
2379
2380 if (pa != null)
2381 {
2382 Vector3 vtmp = pa.CenterOfMass;
2383 return vtmp;
2384 }
2385 else
2386 return new Vector3(0, 0, 0);
2387 */
1931 } 2388 }
1932 2389
1933 public float GetMass() 2390 public float GetMass()
@@ -1940,14 +2397,43 @@ namespace OpenSim.Region.Framework.Scenes
1940 return 0; 2397 return 0;
1941 } 2398 }
1942 2399
1943 public Vector3 GetForce() 2400 public Vector3 GetCenterOfMass()
2401 {
2402 if (ParentGroup.RootPart == this)
2403 {
2404 if (ParentGroup.IsDeleted)
2405 return AbsolutePosition;
2406 return ParentGroup.GetCenterOfMass();
2407 }
2408
2409 PhysicsActor pa = PhysActor;
2410
2411 if (pa != null)
2412 {
2413 Vector3 tmp = pa.CenterOfMass;
2414 return tmp;
2415 }
2416 else
2417 return AbsolutePosition;
2418 }
2419
2420 public Vector3 GetPartCenterOfMass()
1944 { 2421 {
1945 PhysicsActor pa = PhysActor; 2422 PhysicsActor pa = PhysActor;
1946 2423
1947 if (pa != null) 2424 if (pa != null)
1948 return pa.Force; 2425 {
2426 Vector3 tmp = pa.CenterOfMass;
2427 return tmp;
2428 }
1949 else 2429 else
1950 return Vector3.Zero; 2430 return AbsolutePosition;
2431 }
2432
2433
2434 public Vector3 GetForce()
2435 {
2436 return Force;
1951 } 2437 }
1952 2438
1953 /// <summary> 2439 /// <summary>
@@ -2178,45 +2664,87 @@ namespace OpenSim.Region.Framework.Scenes
2178 List<uint> endedColliders = new List<uint>(); 2664 List<uint> endedColliders = new List<uint>();
2179 List<uint> startedColliders = new List<uint>(); 2665 List<uint> startedColliders = new List<uint>();
2180 2666
2181 // calculate things that started colliding this time 2667 if (collissionswith.Count == 0)
2182 // and build up list of colliders this time
2183 foreach (uint localid in collissionswith.Keys)
2184 { 2668 {
2185 thisHitColliders.Add(localid); 2669 if (m_lastColliders.Count == 0)
2186 if (!m_lastColliders.Contains(localid)) 2670 return; // nothing to do
2187 startedColliders.Add(localid);
2188 }
2189 2671
2190 // calculate things that ended colliding 2672 foreach (uint localID in m_lastColliders)
2191 foreach (uint localID in m_lastColliders) 2673 {
2192 {
2193 if (!thisHitColliders.Contains(localID))
2194 endedColliders.Add(localID); 2674 endedColliders.Add(localID);
2675 }
2676 m_lastColliders.Clear();
2195 } 2677 }
2196 2678
2197 //add the items that started colliding this time to the last colliders list. 2679 else
2198 foreach (uint localID in startedColliders) 2680 {
2199 m_lastColliders.Add(localID); 2681 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
2200 2682
2201 // remove things that ended colliding from the last colliders list 2683 // calculate things that started colliding this time
2202 foreach (uint localID in endedColliders) 2684 // and build up list of colliders this time
2203 m_lastColliders.Remove(localID); 2685 if (!VolumeDetectActive && CollisionSoundType >= 0)
2686 {
2687 CollisionForSoundInfo soundinfo;
2688 ContactPoint curcontact;
2204 2689
2205 // play the sound. 2690 foreach (uint id in collissionswith.Keys)
2206 if (startedColliders.Count > 0 && CollisionSound != UUID.Zero && CollisionSoundVolume > 0.0f) 2691 {
2207 SendSound(CollisionSound.ToString(), CollisionSoundVolume, true, (byte)0, 0, false, false); 2692 thisHitColliders.Add(id);
2693 if (!m_lastColliders.Contains(id))
2694 {
2695 startedColliders.Add(id);
2696
2697 curcontact = collissionswith[id];
2698 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
2699 {
2700 soundinfo = new CollisionForSoundInfo();
2701 soundinfo.colliderID = id;
2702 soundinfo.position = curcontact.Position;
2703 soundinfo.relativeVel = curcontact.RelativeSpeed;
2704 soundinfolist.Add(soundinfo);
2705 }
2706 }
2707 }
2708 }
2709 else
2710 {
2711 foreach (uint id in collissionswith.Keys)
2712 {
2713 thisHitColliders.Add(id);
2714 if (!m_lastColliders.Contains(id))
2715 startedColliders.Add(id);
2716 }
2717 }
2718
2719 // calculate things that ended colliding
2720 foreach (uint localID in m_lastColliders)
2721 {
2722 if (!thisHitColliders.Contains(localID))
2723 endedColliders.Add(localID);
2724 }
2725
2726 //add the items that started colliding this time to the last colliders list.
2727 foreach (uint localID in startedColliders)
2728 m_lastColliders.Add(localID);
2729
2730 // remove things that ended colliding from the last colliders list
2731 foreach (uint localID in endedColliders)
2732 m_lastColliders.Remove(localID);
2733
2734 // play sounds.
2735 if (soundinfolist.Count > 0)
2736 CollisionSounds.PartCollisionSound(this, soundinfolist);
2737 }
2208 2738
2209 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); 2739 SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart);
2210 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); 2740 if (!VolumeDetectActive)
2741 SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding);
2211 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); 2742 SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd);
2212 2743
2213 if (startedColliders.Contains(0)) 2744 if (startedColliders.Contains(0))
2214 { 2745 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2215 if (m_lastColliders.Contains(0)) 2746 if (m_lastColliders.Contains(0))
2216 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); 2747 SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding);
2217 else
2218 SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart);
2219 }
2220 if (endedColliders.Contains(0)) 2748 if (endedColliders.Contains(0))
2221 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); 2749 SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd);
2222 } 2750 }
@@ -2239,9 +2767,9 @@ namespace OpenSim.Region.Framework.Scenes
2239 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0); 2767 Vector3 newpos = new Vector3(pa.Position.GetBytes(), 0);
2240 2768
2241 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N) 2769 if (ParentGroup.Scene.TestBorderCross(newpos, Cardinals.N)
2242 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S) 2770 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.S)
2243 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E) 2771 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.E)
2244 | ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W)) 2772 || ParentGroup.Scene.TestBorderCross(newpos, Cardinals.W))
2245 { 2773 {
2246 ParentGroup.AbsolutePosition = newpos; 2774 ParentGroup.AbsolutePosition = newpos;
2247 return; 2775 return;
@@ -2263,17 +2791,18 @@ namespace OpenSim.Region.Framework.Scenes
2263 //Trys to fetch sound id from prim's inventory. 2791 //Trys to fetch sound id from prim's inventory.
2264 //Prim's inventory doesn't support non script items yet 2792 //Prim's inventory doesn't support non script items yet
2265 2793
2266 lock (TaskInventory) 2794 TaskInventory.LockItemsForRead(true);
2795
2796 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2267 { 2797 {
2268 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 2798 if (item.Value.Name == sound)
2269 { 2799 {
2270 if (item.Value.Name == sound) 2800 soundID = item.Value.ItemID;
2271 { 2801 break;
2272 soundID = item.Value.ItemID;
2273 break;
2274 }
2275 } 2802 }
2276 } 2803 }
2804
2805 TaskInventory.LockItemsForRead(false);
2277 } 2806 }
2278 2807
2279 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) 2808 ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp)
@@ -2396,6 +2925,19 @@ namespace OpenSim.Region.Framework.Scenes
2396 APIDTarget = Quaternion.Identity; 2925 APIDTarget = Quaternion.Identity;
2397 } 2926 }
2398 2927
2928
2929
2930 public void ScheduleFullUpdateIfNone()
2931 {
2932 if (ParentGroup == null)
2933 return;
2934
2935// ??? ParentGroup.HasGroupChanged = true;
2936
2937 if (UpdateFlag != UpdateRequired.FULL)
2938 ScheduleFullUpdate();
2939 }
2940
2399 /// <summary> 2941 /// <summary>
2400 /// Schedules this prim for a full update 2942 /// Schedules this prim for a full update
2401 /// </summary> 2943 /// </summary>
@@ -2597,8 +3139,8 @@ namespace OpenSim.Region.Framework.Scenes
2597 { 3139 {
2598 const float ROTATION_TOLERANCE = 0.01f; 3140 const float ROTATION_TOLERANCE = 0.01f;
2599 const float VELOCITY_TOLERANCE = 0.001f; 3141 const float VELOCITY_TOLERANCE = 0.001f;
2600 const float POSITION_TOLERANCE = 0.05f; 3142 const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary
2601 const int TIME_MS_TOLERANCE = 3000; 3143 const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds.
2602 3144
2603 switch (UpdateFlag) 3145 switch (UpdateFlag)
2604 { 3146 {
@@ -2660,17 +3202,16 @@ namespace OpenSim.Region.Framework.Scenes
2660 if (!UUID.TryParse(sound, out soundID)) 3202 if (!UUID.TryParse(sound, out soundID))
2661 { 3203 {
2662 // search sound file from inventory 3204 // search sound file from inventory
2663 lock (TaskInventory) 3205 TaskInventory.LockItemsForRead(true);
3206 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory)
2664 { 3207 {
2665 foreach (KeyValuePair<UUID, TaskInventoryItem> item in TaskInventory) 3208 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound)
2666 { 3209 {
2667 if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) 3210 soundID = item.Value.ItemID;
2668 { 3211 break;
2669 soundID = item.Value.ItemID;
2670 break;
2671 }
2672 } 3212 }
2673 } 3213 }
3214 TaskInventory.LockItemsForRead(false);
2674 } 3215 }
2675 3216
2676 if (soundID == UUID.Zero) 3217 if (soundID == UUID.Zero)
@@ -2727,6 +3268,35 @@ namespace OpenSim.Region.Framework.Scenes
2727 } 3268 }
2728 } 3269 }
2729 3270
3271 public void SendCollisionSound(UUID soundID, double volume, Vector3 position)
3272 {
3273 if (soundID == UUID.Zero)
3274 return;
3275
3276 ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface<ISoundModule>();
3277 if (soundModule == null)
3278 return;
3279
3280 if (volume > 1)
3281 volume = 1;
3282 if (volume < 0)
3283 volume = 0;
3284
3285 int now = Util.EnvironmentTickCount();
3286 if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200)
3287 return;
3288
3289 LastColSoundSentTime = now;
3290
3291 UUID ownerID = OwnerID;
3292 UUID objectID = ParentGroup.RootPart.UUID;
3293 UUID parentID = ParentGroup.UUID;
3294 ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle;
3295
3296 soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 );
3297 }
3298
3299
2730 /// <summary> 3300 /// <summary>
2731 /// Send a terse update to all clients 3301 /// Send a terse update to all clients
2732 /// </summary> 3302 /// </summary>
@@ -2755,10 +3325,13 @@ namespace OpenSim.Region.Framework.Scenes
2755 3325
2756 public void SetBuoyancy(float fvalue) 3326 public void SetBuoyancy(float fvalue)
2757 { 3327 {
2758 PhysicsActor pa = PhysActor; 3328 Buoyancy = fvalue;
2759 3329/*
2760 if (pa != null) 3330 if (PhysActor != null)
2761 pa.Buoyancy = fvalue; 3331 {
3332 PhysActor.Buoyancy = fvalue;
3333 }
3334 */
2762 } 3335 }
2763 3336
2764 public void SetDieAtEdge(bool p) 3337 public void SetDieAtEdge(bool p)
@@ -2774,47 +3347,111 @@ namespace OpenSim.Region.Framework.Scenes
2774 PhysicsActor pa = PhysActor; 3347 PhysicsActor pa = PhysActor;
2775 3348
2776 if (pa != null) 3349 if (pa != null)
2777 pa.FloatOnWater = floatYN == 1; 3350 pa.FloatOnWater = (floatYN == 1);
2778 } 3351 }
2779 3352
2780 public void SetForce(Vector3 force) 3353 public void SetForce(Vector3 force)
2781 { 3354 {
2782 PhysicsActor pa = PhysActor; 3355 Force = force;
3356 }
2783 3357
2784 if (pa != null) 3358 public SOPVehicle sopVehicle
2785 pa.Force = force; 3359 {
3360 get
3361 {
3362 return m_vehicle;
3363 }
3364 set
3365 {
3366 m_vehicle = value;
3367 }
3368 }
3369
3370
3371 public int VehicleType
3372 {
3373 get
3374 {
3375 if (m_vehicle == null)
3376 return (int)Vehicle.TYPE_NONE;
3377 else
3378 return (int)m_vehicle.Type;
3379 }
3380 set
3381 {
3382 SetVehicleType(value);
3383 }
2786 } 3384 }
2787 3385
2788 public void SetVehicleType(int type) 3386 public void SetVehicleType(int type)
2789 { 3387 {
2790 PhysicsActor pa = PhysActor; 3388 m_vehicle = null;
3389
3390 if (type == (int)Vehicle.TYPE_NONE)
3391 {
3392 if (_parentID ==0 && PhysActor != null)
3393 PhysActor.VehicleType = (int)Vehicle.TYPE_NONE;
3394 return;
3395 }
3396 m_vehicle = new SOPVehicle();
3397 m_vehicle.ProcessTypeChange((Vehicle)type);
3398 {
3399 if (_parentID ==0 && PhysActor != null)
3400 PhysActor.VehicleType = type;
3401 return;
3402 }
3403 }
2791 3404
2792 if (pa != null) 3405 public void SetVehicleFlags(int param, bool remove)
2793 pa.VehicleType = type; 3406 {
3407 if (m_vehicle == null)
3408 return;
3409
3410 m_vehicle.ProcessVehicleFlags(param, remove);
3411
3412 if (_parentID ==0 && PhysActor != null)
3413 {
3414 PhysActor.VehicleFlags(param, remove);
3415 }
2794 } 3416 }
2795 3417
2796 public void SetVehicleFloatParam(int param, float value) 3418 public void SetVehicleFloatParam(int param, float value)
2797 { 3419 {
2798 PhysicsActor pa = PhysActor; 3420 if (m_vehicle == null)
3421 return;
2799 3422
2800 if (pa != null) 3423 m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value);
2801 pa.VehicleFloatParam(param, value); 3424
3425 if (_parentID == 0 && PhysActor != null)
3426 {
3427 PhysActor.VehicleFloatParam(param, value);
3428 }
2802 } 3429 }
2803 3430
2804 public void SetVehicleVectorParam(int param, Vector3 value) 3431 public void SetVehicleVectorParam(int param, Vector3 value)
2805 { 3432 {
2806 PhysicsActor pa = PhysActor; 3433 if (m_vehicle == null)
3434 return;
2807 3435
2808 if (pa != null) 3436 m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value);
2809 pa.VehicleVectorParam(param, value); 3437
3438 if (_parentID == 0 && PhysActor != null)
3439 {
3440 PhysActor.VehicleVectorParam(param, value);
3441 }
2810 } 3442 }
2811 3443
2812 public void SetVehicleRotationParam(int param, Quaternion rotation) 3444 public void SetVehicleRotationParam(int param, Quaternion rotation)
2813 { 3445 {
2814 PhysicsActor pa = PhysActor; 3446 if (m_vehicle == null)
3447 return;
2815 3448
2816 if (pa != null) 3449 m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation);
2817 pa.VehicleRotationParam(param, rotation); 3450
3451 if (_parentID == 0 && PhysActor != null)
3452 {
3453 PhysActor.VehicleRotationParam(param, rotation);
3454 }
2818 } 3455 }
2819 3456
2820 /// <summary> 3457 /// <summary>
@@ -2998,14 +3635,6 @@ namespace OpenSim.Region.Framework.Scenes
2998 hasProfileCut = hasDimple; // is it the same thing? 3635 hasProfileCut = hasDimple; // is it the same thing?
2999 } 3636 }
3000 3637
3001 public void SetVehicleFlags(int param, bool remove)
3002 {
3003 PhysicsActor pa = PhysActor;
3004
3005 if (pa != null)
3006 pa.VehicleFlags(param, remove);
3007 }
3008
3009 public void SetGroup(UUID groupID, IClientAPI client) 3638 public void SetGroup(UUID groupID, IClientAPI client)
3010 { 3639 {
3011 // Scene.AddNewPrims() calls with client == null so can't use this. 3640 // Scene.AddNewPrims() calls with client == null so can't use this.
@@ -3109,68 +3738,18 @@ namespace OpenSim.Region.Framework.Scenes
3109 //ParentGroup.ScheduleGroupForFullUpdate(); 3738 //ParentGroup.ScheduleGroupForFullUpdate();
3110 } 3739 }
3111 3740
3112 public void StoreUndoState() 3741 public void StoreUndoState(ObjectChangeType change)
3113 { 3742 {
3114 StoreUndoState(false); 3743 if (m_UndoRedo == null)
3115 } 3744 m_UndoRedo = new UndoRedoState(5);
3116 3745
3117 public void StoreUndoState(bool forGroup) 3746 lock (m_UndoRedo)
3118 {
3119 if (!Undoing)
3120 { 3747 {
3121 if (!IgnoreUndoUpdate) 3748 if (!Undoing && !IgnoreUndoUpdate && ParentGroup != null) // just to read better - undo is in progress, or suspended
3122 { 3749 {
3123 if (ParentGroup != null) 3750 m_UndoRedo.StoreUndo(this, change);
3124 {
3125 lock (m_undo)
3126 {
3127 if (m_undo.Count > 0)
3128 {
3129 UndoState last = m_undo.Peek();
3130 if (last != null)
3131 {
3132 // TODO: May need to fix for group comparison
3133 if (last.Compare(this))
3134 {
3135 // m_log.DebugFormat(
3136 // "[SCENE OBJECT PART]: Not storing undo for {0} {1} since current state is same as last undo state, initial stack size {2}",
3137 // Name, LocalId, m_undo.Count);
3138
3139 return;
3140 }
3141 }
3142 }
3143
3144 // m_log.DebugFormat(
3145 // "[SCENE OBJECT PART]: Storing undo state for {0} {1}, forGroup {2}, initial stack size {3}",
3146 // Name, LocalId, forGroup, m_undo.Count);
3147
3148 if (ParentGroup.GetSceneMaxUndo() > 0)
3149 {
3150 UndoState nUndo = new UndoState(this, forGroup);
3151
3152 m_undo.Push(nUndo);
3153
3154 if (m_redo.Count > 0)
3155 m_redo.Clear();
3156
3157 // m_log.DebugFormat(
3158 // "[SCENE OBJECT PART]: Stored undo state for {0} {1}, forGroup {2}, stack size now {3}",
3159 // Name, LocalId, forGroup, m_undo.Count);
3160 }
3161 }
3162 }
3163 } 3751 }
3164// else
3165// {
3166// m_log.DebugFormat("[SCENE OBJECT PART]: Ignoring undo store for {0} {1}", Name, LocalId);
3167// }
3168 } 3752 }
3169// else
3170// {
3171// m_log.DebugFormat(
3172// "[SCENE OBJECT PART]: Ignoring undo store for {0} {1} since already undoing", Name, LocalId);
3173// }
3174 } 3753 }
3175 3754
3176 /// <summary> 3755 /// <summary>
@@ -3180,84 +3759,46 @@ namespace OpenSim.Region.Framework.Scenes
3180 { 3759 {
3181 get 3760 get
3182 { 3761 {
3183 lock (m_undo) 3762 if (m_UndoRedo == null)
3184 return m_undo.Count; 3763 return 0;
3764 return m_UndoRedo.Count;
3185 } 3765 }
3186 } 3766 }
3187 3767
3188 public void Undo() 3768 public void Undo()
3189 { 3769 {
3190 lock (m_undo) 3770 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3191 { 3771 return;
3192// m_log.DebugFormat(
3193// "[SCENE OBJECT PART]: Handling undo request for {0} {1}, stack size {2}",
3194// Name, LocalId, m_undo.Count);
3195
3196 if (m_undo.Count > 0)
3197 {
3198 UndoState goback = m_undo.Pop();
3199
3200 if (goback != null)
3201 {
3202 UndoState nUndo = null;
3203
3204 if (ParentGroup.GetSceneMaxUndo() > 0)
3205 {
3206 nUndo = new UndoState(this, goback.ForGroup);
3207 }
3208
3209 goback.PlaybackState(this);
3210
3211 if (nUndo != null)
3212 m_redo.Push(nUndo);
3213 }
3214 }
3215 3772
3216// m_log.DebugFormat( 3773 lock (m_UndoRedo)
3217// "[SCENE OBJECT PART]: Handled undo request for {0} {1}, stack size now {2}", 3774 {
3218// Name, LocalId, m_undo.Count); 3775 Undoing = true;
3776 m_UndoRedo.Undo(this);
3777 Undoing = false;
3219 } 3778 }
3220 } 3779 }
3221 3780
3222 public void Redo() 3781 public void Redo()
3223 { 3782 {
3224 lock (m_undo) 3783 if (m_UndoRedo == null || Undoing || ParentGroup == null)
3225 { 3784 return;
3226// m_log.DebugFormat(
3227// "[SCENE OBJECT PART]: Handling redo request for {0} {1}, stack size {2}",
3228// Name, LocalId, m_redo.Count);
3229
3230 if (m_redo.Count > 0)
3231 {
3232 UndoState gofwd = m_redo.Pop();
3233
3234 if (gofwd != null)
3235 {
3236 if (ParentGroup.GetSceneMaxUndo() > 0)
3237 {
3238 UndoState nUndo = new UndoState(this, gofwd.ForGroup);
3239
3240 m_undo.Push(nUndo);
3241 }
3242
3243 gofwd.PlayfwdState(this);
3244 }
3245 3785
3246// m_log.DebugFormat( 3786 lock (m_UndoRedo)
3247// "[SCENE OBJECT PART]: Handled redo request for {0} {1}, stack size now {2}", 3787 {
3248// Name, LocalId, m_redo.Count); 3788 Undoing = true;
3249 } 3789 m_UndoRedo.Redo(this);
3790 Undoing = false;
3250 } 3791 }
3251 } 3792 }
3252 3793
3253 public void ClearUndoState() 3794 public void ClearUndoState()
3254 { 3795 {
3255// m_log.DebugFormat("[SCENE OBJECT PART]: Clearing undo and redo stacks in {0} {1}", Name, LocalId); 3796 if (m_UndoRedo == null || Undoing)
3797 return;
3256 3798
3257 lock (m_undo) 3799 lock (m_UndoRedo)
3258 { 3800 {
3259 m_undo.Clear(); 3801 m_UndoRedo.Clear();
3260 m_redo.Clear();
3261 } 3802 }
3262 } 3803 }
3263 3804
@@ -3887,6 +4428,27 @@ namespace OpenSim.Region.Framework.Scenes
3887 } 4428 }
3888 } 4429 }
3889 4430
4431
4432 public void UpdateExtraPhysics(ExtraPhysicsData physdata)
4433 {
4434 if (physdata.PhysShapeType == PhysShapeType.invalid || ParentGroup == null)
4435 return;
4436
4437 if (PhysicsShapeType != (byte)physdata.PhysShapeType)
4438 {
4439 PhysicsShapeType = (byte)physdata.PhysShapeType;
4440
4441 }
4442
4443 if(Density != physdata.Density)
4444 Density = physdata.Density;
4445 if(GravityModifier != physdata.GravitationModifier)
4446 GravityModifier = physdata.GravitationModifier;
4447 if(Friction != physdata.Friction)
4448 Friction = physdata.Friction;
4449 if(Bounciness != physdata.Bounce)
4450 Bounciness = physdata.Bounce;
4451 }
3890 /// <summary> 4452 /// <summary>
3891 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4453 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
3892 /// </summary> 4454 /// </summary>
@@ -3894,7 +4456,7 @@ namespace OpenSim.Region.Framework.Scenes
3894 /// <param name="SetTemporary"></param> 4456 /// <param name="SetTemporary"></param>
3895 /// <param name="SetPhantom"></param> 4457 /// <param name="SetPhantom"></param>
3896 /// <param name="SetVD"></param> 4458 /// <param name="SetVD"></param>
3897 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD) 4459 public void UpdatePrimFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVD, bool building)
3898 { 4460 {
3899 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0); 4461 bool wasUsingPhysics = ((Flags & PrimFlags.Physics) != 0);
3900 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0); 4462 bool wasTemporary = ((Flags & PrimFlags.TemporaryOnRez) != 0);
@@ -3904,237 +4466,230 @@ namespace OpenSim.Region.Framework.Scenes
3904 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD)) 4466 if ((UsePhysics == wasUsingPhysics) && (wasTemporary == SetTemporary) && (wasPhantom == SetPhantom) && (SetVD == wasVD))
3905 return; 4467 return;
3906 4468
3907 PhysicsActor pa = PhysActor; 4469 VolumeDetectActive = SetVD;
3908 4470
3909 // Special cases for VD. VD can only be called from a script 4471 // volume detector implies phantom
3910 // and can't be combined with changes to other states. So we can rely 4472 if (VolumeDetectActive)
3911 // that...
3912 // ... if VD is changed, all others are not.
3913 // ... if one of the others is changed, VD is not.
3914 if (SetVD) // VD is active, special logic applies
3915 {
3916 // State machine logic for VolumeDetect
3917 // More logic below
3918 bool phanReset = (SetPhantom != wasPhantom) && !SetPhantom;
3919
3920 if (phanReset) // Phantom changes from on to off switch VD off too
3921 {
3922 SetVD = false; // Switch it of for the course of this routine
3923 VolumeDetectActive = false; // and also permanently
3924
3925 if (pa != null)
3926 pa.SetVolumeDetect(0); // Let physics know about it too
3927 }
3928 else
3929 {
3930 // If volumedetect is active we don't want phantom to be applied.
3931 // If this is a new call to VD out of the state "phantom"
3932 // this will also cause the prim to be visible to physics
3933 SetPhantom = false;
3934 }
3935 }
3936
3937 if (UsePhysics && IsJoint())
3938 {
3939 SetPhantom = true; 4473 SetPhantom = true;
3940 }
3941 4474
3942 if (UsePhysics) 4475 if (UsePhysics)
3943 {
3944 AddFlag(PrimFlags.Physics); 4476 AddFlag(PrimFlags.Physics);
3945 if (!wasUsingPhysics)
3946 {
3947 DoPhysicsPropertyUpdate(UsePhysics, false);
3948
3949 if (!ParentGroup.IsDeleted)
3950 {
3951 if (LocalId == ParentGroup.RootPart.LocalId)
3952 {
3953 ParentGroup.CheckSculptAndLoad();
3954 }
3955 }
3956 }
3957 }
3958 else 4477 else
3959 {
3960 RemFlag(PrimFlags.Physics); 4478 RemFlag(PrimFlags.Physics);
3961 if (wasUsingPhysics)
3962 {
3963 DoPhysicsPropertyUpdate(UsePhysics, false);
3964 }
3965 }
3966 4479
3967 if (SetPhantom 4480 if (SetPhantom)
3968 || ParentGroup.IsAttachment
3969 || (Shape.PathCurve == (byte)Extrusion.Flexible)) // note: this may have been changed above in the case of joints
3970 {
3971 AddFlag(PrimFlags.Phantom); 4481 AddFlag(PrimFlags.Phantom);
3972 4482 else
3973 if (PhysActor != null)
3974 {
3975 RemoveFromPhysics();
3976 pa = null;
3977 }
3978 }
3979 else // Not phantom
3980 {
3981 RemFlag(PrimFlags.Phantom); 4483 RemFlag(PrimFlags.Phantom);
3982 4484
3983 if (ParentGroup.Scene == null) 4485 if (SetTemporary)
3984 return; 4486 AddFlag(PrimFlags.TemporaryOnRez);
4487 else
4488 RemFlag(PrimFlags.TemporaryOnRez);
3985 4489
3986 if (ParentGroup.Scene.CollidablePrims && pa == null)
3987 {
3988 pa = AddToPhysics(UsePhysics);
3989 4490
3990 if (pa != null) 4491 if (ParentGroup.Scene == null)
3991 { 4492 return;
3992 pa.SetMaterial(Material);
3993 DoPhysicsPropertyUpdate(UsePhysics, true);
3994
3995 if (!ParentGroup.IsDeleted)
3996 {
3997 if (LocalId == ParentGroup.RootPart.LocalId)
3998 {
3999 ParentGroup.CheckSculptAndLoad();
4000 }
4001 }
4002
4003 if (
4004 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4005 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4006 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4007 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4008 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4009 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4010 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4011 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4012 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4013 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4014 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4015 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4016 (CollisionSound != UUID.Zero)
4017 )
4018 {
4019 pa.OnCollisionUpdate += PhysicsCollision;
4020 pa.SubscribeEvents(1000);
4021 }
4022 }
4023 }
4024 else // it already has a physical representation
4025 {
4026 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status. If it's phantom this will remove the prim
4027 4493
4028 if (!ParentGroup.IsDeleted) 4494 PhysicsActor pa = PhysActor;
4029 { 4495
4030 if (LocalId == ParentGroup.RootPart.LocalId) 4496 if (pa != null && building && pa.Building != building)
4031 { 4497 pa.Building = building;
4032 ParentGroup.CheckSculptAndLoad();
4033 }
4034 }
4035 }
4036 }
4037 4498
4038 if (SetVD) 4499 if ((SetPhantom && !UsePhysics && !SetVD) || ParentGroup.IsAttachment || PhysicsShapeType == (byte)PhysShapeType.none
4500 || (Shape.PathCurve == (byte)Extrusion.Flexible))
4039 { 4501 {
4040 // If the above logic worked (this is urgent candidate to unit tests!)
4041 // we now have a physicsactor.
4042 // Defensive programming calls for a check here.
4043 // Better would be throwing an exception that could be catched by a unit test as the internal
4044 // logic should make sure, this Physactor is always here.
4045 if (pa != null) 4502 if (pa != null)
4046 { 4503 {
4047 pa.SetVolumeDetect(1); 4504 ParentGroup.Scene.RemovePhysicalPrim(1);
4048 AddFlag(PrimFlags.Phantom); // We set this flag also if VD is active 4505 RemoveFromPhysics();
4049 VolumeDetectActive = true;
4050 } 4506 }
4507
4508 Velocity = new Vector3(0, 0, 0);
4509 Acceleration = new Vector3(0, 0, 0);
4510 if (ParentGroup.RootPart == this)
4511 AngularVelocity = new Vector3(0, 0, 0);
4051 } 4512 }
4052 else 4513 else
4053 { 4514 {
4054 // Remove VolumeDetect in any case. Note, it's safe to call SetVolumeDetect as often as you like 4515 if (ParentGroup.Scene.CollidablePrims)
4055 // (mumbles, well, at least if you have infinte CPU powers :-)) 4516 {
4056 if (pa != null) 4517 if (pa == null)
4057 pa.SetVolumeDetect(0); 4518 {
4519 AddToPhysics(UsePhysics, SetPhantom, building, false);
4520 pa = PhysActor;
4521 /*
4522 if (pa != null)
4523 {
4524 if (
4525 // ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4526 // ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4527 // ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4528 // ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4529 // ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4530 // ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4531 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4532 ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) ||
4533 (CollisionSound != UUID.Zero)
4534 )
4535 {
4536 pa.OnCollisionUpdate += PhysicsCollision;
4537 pa.SubscribeEvents(1000);
4538 }
4539 }
4540 */
4541 }
4542 else // it already has a physical representation
4543 {
4544 DoPhysicsPropertyUpdate(UsePhysics, false); // Update physical status.
4545 /* moved into DoPhysicsPropertyUpdate
4546 if(VolumeDetectActive)
4547 pa.SetVolumeDetect(1);
4548 else
4549 pa.SetVolumeDetect(0);
4550 */
4058 4551
4059 VolumeDetectActive = false;
4060 }
4061 4552
4062 if (SetTemporary) 4553 if (pa.Building != building)
4063 { 4554 pa.Building = building;
4064 AddFlag(PrimFlags.TemporaryOnRez); 4555 }
4065 } 4556
4066 else 4557 UpdatePhysicsSubscribedEvents();
4067 { 4558 }
4068 RemFlag(PrimFlags.TemporaryOnRez); 4559 }
4069 }
4070 4560
4071 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString()); 4561 // m_log.Debug("Update: PHY:" + UsePhysics.ToString() + ", T:" + IsTemporary.ToString() + ", PHA:" + IsPhantom.ToString() + " S:" + CastsShadows.ToString());
4072 4562
4563 // and last in case we have a new actor and not building
4564
4073 if (ParentGroup != null) 4565 if (ParentGroup != null)
4074 { 4566 {
4075 ParentGroup.HasGroupChanged = true; 4567 ParentGroup.HasGroupChanged = true;
4076 ScheduleFullUpdate(); 4568 ScheduleFullUpdate();
4077 } 4569 }
4078 4570
4079// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags); 4571// m_log.DebugFormat("[SCENE OBJECT PART]: Updated PrimFlags on {0} {1} to {2}", Name, LocalId, Flags);
4080 } 4572 }
4081 4573
4082 /// <summary> 4574 /// <summary>
4083 /// Adds this part to the physics scene. 4575 /// Adds this part to the physics scene.
4576 /// and sets the PhysActor property
4084 /// </summary> 4577 /// </summary>
4085 /// <remarks>This method also sets the PhysActor property.</remarks> 4578 /// <param name="isPhysical">Add this prim as physical.</param>
4086 /// <param name="rigidBody">Add this prim with a rigid body.</param> 4579 /// <param name="isPhantom">Add this prim as phantom.</param>
4087 /// <returns> 4580 /// <param name="building">tells physics to delay full construction of object</param>
4088 /// The physics actor. null if there was a failure. 4581 /// <param name="applyDynamics">applies velocities, force and torque</param>
4089 /// </returns> 4582 private void AddToPhysics(bool isPhysical, bool isPhantom, bool building, bool applyDynamics)
4090 private PhysicsActor AddToPhysics(bool rigidBody) 4583 {
4091 {
4092 PhysicsActor pa; 4584 PhysicsActor pa;
4093 4585
4586 Vector3 velocity = Velocity;
4587 Vector3 rotationalVelocity = AngularVelocity;;
4588
4094 try 4589 try
4095 { 4590 {
4096 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape( 4591 pa = ParentGroup.Scene.PhysicsScene.AddPrimShape(
4097 string.Format("{0}/{1}", Name, UUID), 4592 string.Format("{0}/{1}", Name, UUID),
4098 Shape, 4593 Shape,
4099 AbsolutePosition, 4594 AbsolutePosition,
4100 Scale, 4595 Scale,
4101 RotationOffset, 4596 GetWorldRotation(),
4102 rigidBody, 4597 isPhysical,
4103 m_localId); 4598 isPhantom,
4599 PhysicsShapeType,
4600 m_localId);
4104 } 4601 }
4105 catch 4602 catch (Exception ex)
4106 { 4603 {
4107 m_log.ErrorFormat("[SCENE]: caught exception meshing object {0}. Object set to phantom.", m_uuid); 4604 m_log.ErrorFormat("[SCENE]: AddToPhysics object {0} failed: {1}", m_uuid, ex.Message);
4108 pa = null; 4605 pa = null;
4109 } 4606 }
4110 4607
4111 // FIXME: Ideally we wouldn't set the property here to reduce situations where threads changing physical
4112 // properties can stop on each other. However, DoPhysicsPropertyUpdate() currently relies on PhysActor
4113 // being set.
4114 PhysActor = pa;
4115
4116 // Basic Physics can also return null as well as an exception catch.
4117 if (pa != null) 4608 if (pa != null)
4118 { 4609 {
4119 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4610 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4120 pa.SetMaterial(Material); 4611 pa.SetMaterial(Material);
4121 DoPhysicsPropertyUpdate(rigidBody, true); 4612
4613 if (VolumeDetectActive) // change if not the default only
4614 pa.SetVolumeDetect(1);
4615
4616 if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId)
4617 m_vehicle.SetVehicle(pa);
4618
4619 // we are going to tell rest of code about physics so better have this here
4620 PhysActor = pa;
4621
4622 // DoPhysicsPropertyUpdate(isPhysical, true);
4623 // lets expand it here just with what it really needs to do
4624
4625 if (isPhysical)
4626 {
4627 if (ParentGroup.RootPart.KeyframeMotion != null)
4628 ParentGroup.RootPart.KeyframeMotion.Stop();
4629 ParentGroup.RootPart.KeyframeMotion = null;
4630 ParentGroup.Scene.AddPhysicalPrim(1);
4631
4632 pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate;
4633 pa.OnOutOfBounds += PhysicsOutOfBounds;
4634
4635 if (ParentID != 0 && ParentID != LocalId)
4636 {
4637 PhysicsActor parentPa = ParentGroup.RootPart.PhysActor;
4638
4639 if (parentPa != null)
4640 {
4641 pa.link(parentPa);
4642 }
4643 }
4644 }
4645
4646 if (applyDynamics)
4647 // do independent of isphysical so parameters get setted (at least some)
4648 {
4649 Velocity = velocity;
4650 AngularVelocity = rotationalVelocity;
4651// pa.Velocity = velocity;
4652 pa.RotationalVelocity = rotationalVelocity;
4653
4654 // if not vehicle and root part apply force and torque
4655 if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE)
4656 && LocalId == ParentGroup.RootPart.LocalId)
4657 {
4658 pa.Force = Force;
4659 pa.Torque = Torque;
4660 }
4661 }
4662
4663 if (Shape.SculptEntry)
4664 CheckSculptAndLoad();
4665 else
4666 ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(pa);
4667
4668 if (!building)
4669 pa.Building = false;
4122 } 4670 }
4123 4671
4124 return pa; 4672 PhysActor = pa;
4125 } 4673 }
4126 4674
4127 /// <summary> 4675 /// <summary>
4128 /// This removes the part from the physics scene. 4676 /// This removes the part from the physics scene.
4129 /// </summary> 4677 /// </summary>
4130 /// <remarks> 4678 /// <remarks>
4131 /// This isn't the same as turning off physical, since even without being physical the prim has a physics 4679 /// This isn't the same as turning off physical, since even without being physical the prim has a physics
4132 /// representation for collision detection. Rather, this would be used in situations such as making a prim 4680 /// representation for collision detection.
4133 /// phantom.
4134 /// </remarks> 4681 /// </remarks>
4135 public void RemoveFromPhysics() 4682 public void RemoveFromPhysics()
4136 { 4683 {
4137 ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor); 4684 PhysicsActor pa = PhysActor;
4685 if (pa != null)
4686 {
4687 pa.OnCollisionUpdate -= PhysicsCollision;
4688 pa.OnRequestTerseUpdate -= PhysicsRequestingTerseUpdate;
4689 pa.OnOutOfBounds -= PhysicsOutOfBounds;
4690
4691 ParentGroup.Scene.PhysicsScene.RemovePrim(pa);
4692 }
4138 PhysActor = null; 4693 PhysActor = null;
4139 } 4694 }
4140 4695
@@ -4294,6 +4849,44 @@ namespace OpenSim.Region.Framework.Scenes
4294 ScheduleFullUpdate(); 4849 ScheduleFullUpdate();
4295 } 4850 }
4296 4851
4852
4853 private void UpdatePhysicsSubscribedEvents()
4854 {
4855 PhysicsActor pa = PhysActor;
4856 if (pa == null)
4857 return;
4858
4859 pa.OnCollisionUpdate -= PhysicsCollision;
4860
4861 bool hassound = (CollisionSoundType >= 0 && !VolumeDetectActive);
4862
4863 scriptEvents CombinedEvents = AggregateScriptEvents;
4864
4865 // merge with root part
4866 if (ParentGroup != null && ParentGroup.RootPart != null)
4867 CombinedEvents |= ParentGroup.RootPart.AggregateScriptEvents;
4868
4869 // submit to this part case
4870 if (VolumeDetectActive)
4871 CombinedEvents &= PhyscicsVolumeDtcSubsEvents;
4872 else if ((Flags & PrimFlags.Phantom) != 0)
4873 CombinedEvents &= PhyscicsPhantonSubsEvents;
4874 else
4875 CombinedEvents &= PhysicsNeededSubsEvents;
4876
4877 if (hassound || CombinedEvents != 0)
4878 {
4879 // subscribe to physics updates.
4880 pa.OnCollisionUpdate += PhysicsCollision;
4881 pa.SubscribeEvents(50); // 20 reports per second
4882 }
4883 else
4884 {
4885 pa.UnSubscribeEvents();
4886 }
4887 }
4888
4889
4297 public void aggregateScriptEvents() 4890 public void aggregateScriptEvents()
4298 { 4891 {
4299 if (ParentGroup == null || ParentGroup.RootPart == null) 4892 if (ParentGroup == null || ParentGroup.RootPart == null)
@@ -4330,40 +4923,32 @@ namespace OpenSim.Region.Framework.Scenes
4330 { 4923 {
4331 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop; 4924 objectflagupdate |= (uint) PrimFlags.AllowInventoryDrop;
4332 } 4925 }
4333 4926/*
4334 PhysicsActor pa = PhysActor; 4927 PhysicsActor pa = PhysActor;
4335 4928 if (pa != null)
4336 if (
4337 ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4338 ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4339 ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4340 ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4341 ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4342 ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4343 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision) != 0) ||
4344 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4345 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4346 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4347 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4348 ((ParentGroup.RootPart.AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4349 (CollisionSound != UUID.Zero)
4350 )
4351 { 4929 {
4352 // subscribe to physics updates. 4930 if (
4353 if (pa != null) 4931// ((AggregateScriptEvents & scriptEvents.collision) != 0) ||
4932// ((AggregateScriptEvents & scriptEvents.collision_end) != 0) ||
4933// ((AggregateScriptEvents & scriptEvents.collision_start) != 0) ||
4934// ((AggregateScriptEvents & scriptEvents.land_collision_start) != 0) ||
4935// ((AggregateScriptEvents & scriptEvents.land_collision) != 0) ||
4936// ((AggregateScriptEvents & scriptEvents.land_collision_end) != 0) ||
4937 ((AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || ((ParentGroup.RootPart.AggregateScriptEvents & PhysicsNeededSubsEvents) != 0) || (CollisionSound != UUID.Zero)
4938 )
4354 { 4939 {
4940 // subscribe to physics updates.
4355 pa.OnCollisionUpdate += PhysicsCollision; 4941 pa.OnCollisionUpdate += PhysicsCollision;
4356 pa.SubscribeEvents(1000); 4942 pa.SubscribeEvents(1000);
4357 } 4943 }
4358 } 4944 else
4359 else
4360 {
4361 if (pa != null)
4362 { 4945 {
4363 pa.UnSubscribeEvents(); 4946 pa.UnSubscribeEvents();
4364 pa.OnCollisionUpdate -= PhysicsCollision; 4947 pa.OnCollisionUpdate -= PhysicsCollision;
4365 } 4948 }
4366 } 4949 }
4950 */
4951 UpdatePhysicsSubscribedEvents();
4367 4952
4368 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0) 4953 //if ((GetEffectiveObjectFlags() & (uint)PrimFlags.Scripted) != 0)
4369 //{ 4954 //{
@@ -4491,5 +5076,17 @@ namespace OpenSim.Region.Framework.Scenes
4491 Color color = Color; 5076 Color color = Color;
4492 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A)); 5077 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4493 } 5078 }
5079
5080 public void ResetOwnerChangeFlag()
5081 {
5082 List<UUID> inv = Inventory.GetInventoryList();
5083
5084 foreach (UUID itemID in inv)
5085 {
5086 TaskInventoryItem item = Inventory.GetInventoryItem(itemID);
5087 item.OwnerChanged = false;
5088 Inventory.UpdateInventoryItem(item, false, false);
5089 }
5090 }
4494 } 5091 }
4495} 5092}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 8810903..f5b9825 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>
@@ -257,7 +302,10 @@ namespace OpenSim.Region.Framework.Scenes
257 { 302 {
258 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL); 303 List<TaskInventoryItem> scripts = GetInventoryItems(InventoryType.LSL);
259 foreach (TaskInventoryItem item in scripts) 304 foreach (TaskInventoryItem item in scripts)
305 {
260 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted); 306 RemoveScriptInstance(item.ItemID, sceneObjectBeingDeleted);
307 m_part.RemoveScriptEvents(item.ItemID);
308 }
261 } 309 }
262 310
263 /// <summary> 311 /// <summary>
@@ -271,7 +319,10 @@ namespace OpenSim.Region.Framework.Scenes
271// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); 319// item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName);
272 320
273 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) 321 if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID))
322 {
323 StoreScriptError(item.ItemID, "no permission");
274 return; 324 return;
325 }
275 326
276 m_part.AddFlag(PrimFlags.Scripted); 327 m_part.AddFlag(PrimFlags.Scripted);
277 328
@@ -280,14 +331,13 @@ namespace OpenSim.Region.Framework.Scenes
280 if (stateSource == 2 && // Prim crossing 331 if (stateSource == 2 && // Prim crossing
281 m_part.ParentGroup.Scene.m_trustBinaries) 332 m_part.ParentGroup.Scene.m_trustBinaries)
282 { 333 {
283 lock (m_items) 334 m_items.LockItemsForWrite(true);
284 { 335 m_items[item.ItemID].PermsMask = 0;
285 m_items[item.ItemID].PermsMask = 0; 336 m_items[item.ItemID].PermsGranter = UUID.Zero;
286 m_items[item.ItemID].PermsGranter = UUID.Zero; 337 m_items.LockItemsForWrite(false);
287 }
288
289 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 338 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
290 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); 339 m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource);
340 StoreScriptErrors(item.ItemID, null);
291 m_part.ParentGroup.AddActiveScriptCount(1); 341 m_part.ParentGroup.AddActiveScriptCount(1);
292 m_part.ScheduleFullUpdate(); 342 m_part.ScheduleFullUpdate();
293 return; 343 return;
@@ -296,6 +346,8 @@ namespace OpenSim.Region.Framework.Scenes
296 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString()); 346 AssetBase asset = m_part.ParentGroup.Scene.AssetService.Get(item.AssetID.ToString());
297 if (null == asset) 347 if (null == asset)
298 { 348 {
349 string msg = String.Format("asset ID {0} could not be found", item.AssetID);
350 StoreScriptError(item.ItemID, msg);
299 m_log.ErrorFormat( 351 m_log.ErrorFormat(
300 "[PRIM INVENTORY]: Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", 352 "[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, 353 item.Name, item.ItemID, m_part.AbsolutePosition,
@@ -306,16 +358,21 @@ namespace OpenSim.Region.Framework.Scenes
306 if (m_part.ParentGroup.m_savedScriptState != null) 358 if (m_part.ParentGroup.m_savedScriptState != null)
307 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID); 359 item.OldItemID = RestoreSavedScriptState(item.LoadedItemID, item.OldItemID, item.ItemID);
308 360
309 lock (m_items) 361 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 362
363 m_items[item.ItemID].OldItemID = item.OldItemID;
364 m_items[item.ItemID].PermsMask = 0;
365 m_items[item.ItemID].PermsGranter = UUID.Zero;
366
367 m_items.LockItemsForWrite(false);
368
316 string script = Utils.BytesToString(asset.Data); 369 string script = Utils.BytesToString(asset.Data);
317 m_part.ParentGroup.Scene.EventManager.TriggerRezScript( 370 m_part.ParentGroup.Scene.EventManager.TriggerRezScript(
318 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); 371 m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource);
372 StoreScriptErrors(item.ItemID, null);
373 if (!item.ScriptRunning)
374 m_part.ParentGroup.Scene.EventManager.TriggerStopScript(
375 m_part.LocalId, item.ItemID);
319 m_part.ParentGroup.AddActiveScriptCount(1); 376 m_part.ParentGroup.AddActiveScriptCount(1);
320 m_part.ScheduleFullUpdate(); 377 m_part.ScheduleFullUpdate();
321 } 378 }
@@ -386,20 +443,146 @@ namespace OpenSim.Region.Framework.Scenes
386 443
387 /// <summary> 444 /// <summary>
388 /// Start a script which is in this prim's inventory. 445 /// Start a script which is in this prim's inventory.
446 /// Some processing may occur in the background, but this routine returns asap.
389 /// </summary> 447 /// </summary>
390 /// <param name="itemId"> 448 /// <param name="itemId">
391 /// A <see cref="UUID"/> 449 /// A <see cref="UUID"/>
392 /// </param> 450 /// </param>
393 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) 451 public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
394 { 452 {
395 TaskInventoryItem item = GetInventoryItem(itemId); 453 lock (m_scriptErrors)
396 if (item != null) 454 {
397 CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); 455 // Indicate to CreateScriptInstanceInternal() we don't want it to wait for completion
456 m_scriptErrors.Remove(itemId);
457 }
458 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
459 }
460
461 private void CreateScriptInstanceInternal(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
462 {
463 m_items.LockItemsForRead(true);
464 if (m_items.ContainsKey(itemId))
465 {
466 if (m_items.ContainsKey(itemId))
467 {
468 m_items.LockItemsForRead(false);
469 CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource);
470 }
471 else
472 {
473 m_items.LockItemsForRead(false);
474 string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID,
475 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
476 StoreScriptError(itemId, msg);
477 m_log.ErrorFormat(
478 "[PRIM INVENTORY]: " +
479 "Couldn't start script with ID {0} since it {1}", itemId, msg);
480 }
481 }
398 else 482 else
483 {
484 m_items.LockItemsForRead(false);
485 string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID);
486 StoreScriptError(itemId, msg);
399 m_log.ErrorFormat( 487 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}", 488 "[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, 489 itemId, m_part.Name, m_part.UUID,
402 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 490 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
491 }
492
493 }
494
495 /// <summary>
496 /// Start a script which is in this prim's inventory and return any compilation error messages.
497 /// </summary>
498 /// <param name="itemId">
499 /// A <see cref="UUID"/>
500 /// </param>
501 public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource)
502 {
503 ArrayList errors;
504
505 // Indicate to CreateScriptInstanceInternal() we want it to
506 // post any compilation/loading error messages
507 lock (m_scriptErrors)
508 {
509 m_scriptErrors[itemId] = null;
510 }
511
512 // Perform compilation/loading
513 CreateScriptInstanceInternal(itemId, startParam, postOnRez, engine, stateSource);
514
515 // Wait for and retrieve any errors
516 lock (m_scriptErrors)
517 {
518 while ((errors = m_scriptErrors[itemId]) == null)
519 {
520 if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000))
521 {
522 m_log.ErrorFormat(
523 "[PRIM INVENTORY]: " +
524 "timedout waiting for script {0} errors", itemId);
525 errors = m_scriptErrors[itemId];
526 if (errors == null)
527 {
528 errors = new ArrayList(1);
529 errors.Add("timedout waiting for errors");
530 }
531 break;
532 }
533 }
534 m_scriptErrors.Remove(itemId);
535 }
536 return errors;
537 }
538
539 // Signal to CreateScriptInstanceEr() that compilation/loading is complete
540 private void StoreScriptErrors(UUID itemId, ArrayList errors)
541 {
542 lock (m_scriptErrors)
543 {
544 // If compilation/loading initiated via CreateScriptInstance(),
545 // it does not want the errors, so just get out
546 if (!m_scriptErrors.ContainsKey(itemId))
547 {
548 return;
549 }
550
551 // Initiated via CreateScriptInstanceEr(), if we know what the
552 // errors are, save them and wake CreateScriptInstanceEr().
553 if (errors != null)
554 {
555 m_scriptErrors[itemId] = errors;
556 System.Threading.Monitor.PulseAll(m_scriptErrors);
557 return;
558 }
559 }
560
561 // Initiated via CreateScriptInstanceEr() but we don't know what
562 // the errors are yet, so retrieve them from the script engine.
563 // This may involve some waiting internal to GetScriptErrors().
564 errors = GetScriptErrors(itemId);
565
566 // Get a default non-null value to indicate success.
567 if (errors == null)
568 {
569 errors = new ArrayList();
570 }
571
572 // Post to CreateScriptInstanceEr() and wake it up
573 lock (m_scriptErrors)
574 {
575 m_scriptErrors[itemId] = errors;
576 System.Threading.Monitor.PulseAll(m_scriptErrors);
577 }
578 }
579
580 // Like StoreScriptErrors(), but just posts a single string message
581 private void StoreScriptError(UUID itemId, string message)
582 {
583 ArrayList errors = new ArrayList(1);
584 errors.Add(message);
585 StoreScriptErrors(itemId, errors);
403 } 586 }
404 587
405 /// <summary> 588 /// <summary>
@@ -412,15 +595,7 @@ namespace OpenSim.Region.Framework.Scenes
412 /// </param> 595 /// </param>
413 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted) 596 public void RemoveScriptInstance(UUID itemId, bool sceneObjectBeingDeleted)
414 { 597 {
415 bool scriptPresent = false; 598 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 { 599 {
425 if (!sceneObjectBeingDeleted) 600 if (!sceneObjectBeingDeleted)
426 m_part.RemoveScriptEvents(itemId); 601 m_part.RemoveScriptEvents(itemId);
@@ -445,14 +620,16 @@ namespace OpenSim.Region.Framework.Scenes
445 /// <returns></returns> 620 /// <returns></returns>
446 private bool InventoryContainsName(string name) 621 private bool InventoryContainsName(string name)
447 { 622 {
448 lock (m_items) 623 m_items.LockItemsForRead(true);
624 foreach (TaskInventoryItem item in m_items.Values)
449 { 625 {
450 foreach (TaskInventoryItem item in m_items.Values) 626 if (item.Name == name)
451 { 627 {
452 if (item.Name == name) 628 m_items.LockItemsForRead(false);
453 return true; 629 return true;
454 } 630 }
455 } 631 }
632 m_items.LockItemsForRead(false);
456 return false; 633 return false;
457 } 634 }
458 635
@@ -494,8 +671,9 @@ namespace OpenSim.Region.Framework.Scenes
494 /// <param name="item"></param> 671 /// <param name="item"></param>
495 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) 672 public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop)
496 { 673 {
497 List<TaskInventoryItem> il = GetInventoryItems(); 674 m_items.LockItemsForRead(true);
498 675 List<TaskInventoryItem> il = new List<TaskInventoryItem>(m_items.Values);
676 m_items.LockItemsForRead(false);
499 foreach (TaskInventoryItem i in il) 677 foreach (TaskInventoryItem i in il)
500 { 678 {
501 if (i.Name == item.Name) 679 if (i.Name == item.Name)
@@ -533,14 +711,14 @@ namespace OpenSim.Region.Framework.Scenes
533 item.Name = name; 711 item.Name = name;
534 item.GroupID = m_part.GroupID; 712 item.GroupID = m_part.GroupID;
535 713
536 lock (m_items) 714 m_items.LockItemsForWrite(true);
537 m_items.Add(item.ItemID, item); 715 m_items.Add(item.ItemID, item);
538 716 m_items.LockItemsForWrite(false);
539 if (allowedDrop) 717 if (allowedDrop)
540 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); 718 m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP);
541 else 719 else
542 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 720 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
543 721
544 m_inventorySerial++; 722 m_inventorySerial++;
545 //m_inventorySerial += 2; 723 //m_inventorySerial += 2;
546 HasInventoryChanged = true; 724 HasInventoryChanged = true;
@@ -556,15 +734,15 @@ namespace OpenSim.Region.Framework.Scenes
556 /// <param name="items"></param> 734 /// <param name="items"></param>
557 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items) 735 public void RestoreInventoryItems(ICollection<TaskInventoryItem> items)
558 { 736 {
559 lock (m_items) 737 m_items.LockItemsForWrite(true);
738 foreach (TaskInventoryItem item in items)
560 { 739 {
561 foreach (TaskInventoryItem item in items) 740 m_items.Add(item.ItemID, item);
562 { 741// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
563 m_items.Add(item.ItemID, item);
564// m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
565 }
566 m_inventorySerial++;
567 } 742 }
743 m_items.LockItemsForWrite(false);
744
745 m_inventorySerial++;
568 } 746 }
569 747
570 /// <summary> 748 /// <summary>
@@ -575,23 +753,24 @@ namespace OpenSim.Region.Framework.Scenes
575 public TaskInventoryItem GetInventoryItem(UUID itemId) 753 public TaskInventoryItem GetInventoryItem(UUID itemId)
576 { 754 {
577 TaskInventoryItem item; 755 TaskInventoryItem item;
578 756 m_items.LockItemsForRead(true);
579 lock (m_items) 757 m_items.TryGetValue(itemId, out item);
580 m_items.TryGetValue(itemId, out item); 758 m_items.LockItemsForRead(false);
581
582 return item; 759 return item;
583 } 760 }
584 761
585 public TaskInventoryItem GetInventoryItem(string name) 762 public TaskInventoryItem GetInventoryItem(string name)
586 { 763 {
587 lock (m_items) 764 m_items.LockItemsForRead(true);
765 foreach (TaskInventoryItem item in m_items.Values)
588 { 766 {
589 foreach (TaskInventoryItem item in m_items.Values) 767 if (item.Name == name)
590 { 768 {
591 if (item.Name == name) 769 return item;
592 return item; 770 m_items.LockItemsForRead(false);
593 } 771 }
594 } 772 }
773 m_items.LockItemsForRead(false);
595 774
596 return null; 775 return null;
597 } 776 }
@@ -600,15 +779,16 @@ namespace OpenSim.Region.Framework.Scenes
600 { 779 {
601 List<TaskInventoryItem> items = new List<TaskInventoryItem>(); 780 List<TaskInventoryItem> items = new List<TaskInventoryItem>();
602 781
603 lock (m_items) 782 m_items.LockItemsForRead(true);
783
784 foreach (TaskInventoryItem item in m_items.Values)
604 { 785 {
605 foreach (TaskInventoryItem item in m_items.Values) 786 if (item.Name == name)
606 { 787 items.Add(item);
607 if (item.Name == name)
608 items.Add(item);
609 }
610 } 788 }
611 789
790 m_items.LockItemsForRead(false);
791
612 return items; 792 return items;
613 } 793 }
614 794
@@ -627,6 +807,10 @@ namespace OpenSim.Region.Framework.Scenes
627 string xmlData = Utils.BytesToString(rezAsset.Data); 807 string xmlData = Utils.BytesToString(rezAsset.Data);
628 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); 808 SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(xmlData);
629 809
810 group.RootPart.AttachPoint = group.RootPart.Shape.State;
811 group.RootPart.AttachOffset = group.AbsolutePosition;
812 group.RootPart.AttachRotation = group.GroupRotation;
813
630 group.ResetIDs(); 814 group.ResetIDs();
631 815
632 SceneObjectPart rootPart = group.GetPart(group.UUID); 816 SceneObjectPart rootPart = group.GetPart(group.UUID);
@@ -701,8 +885,9 @@ namespace OpenSim.Region.Framework.Scenes
701 885
702 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged) 886 public bool UpdateInventoryItem(TaskInventoryItem item, bool fireScriptEvents, bool considerChanged)
703 { 887 {
704 TaskInventoryItem it = GetInventoryItem(item.ItemID); 888 m_items.LockItemsForWrite(true);
705 if (it != null) 889
890 if (m_items.ContainsKey(item.ItemID))
706 { 891 {
707// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name); 892// m_log.DebugFormat("[PRIM INVENTORY]: Updating item {0} in {1}", item.Name, m_part.Name);
708 893
@@ -715,14 +900,10 @@ namespace OpenSim.Region.Framework.Scenes
715 item.GroupID = m_part.GroupID; 900 item.GroupID = m_part.GroupID;
716 901
717 if (item.AssetID == UUID.Zero) 902 if (item.AssetID == UUID.Zero)
718 item.AssetID = it.AssetID; 903 item.AssetID = m_items[item.ItemID].AssetID;
719 904
720 lock (m_items) 905 m_items[item.ItemID] = item;
721 { 906 m_inventorySerial++;
722 m_items[item.ItemID] = item;
723 m_inventorySerial++;
724 }
725
726 if (fireScriptEvents) 907 if (fireScriptEvents)
727 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 908 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
728 909
@@ -731,7 +912,7 @@ namespace OpenSim.Region.Framework.Scenes
731 HasInventoryChanged = true; 912 HasInventoryChanged = true;
732 m_part.ParentGroup.HasGroupChanged = true; 913 m_part.ParentGroup.HasGroupChanged = true;
733 } 914 }
734 915 m_items.LockItemsForWrite(false);
735 return true; 916 return true;
736 } 917 }
737 else 918 else
@@ -742,8 +923,9 @@ namespace OpenSim.Region.Framework.Scenes
742 item.ItemID, m_part.Name, m_part.UUID, 923 item.ItemID, m_part.Name, m_part.UUID,
743 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); 924 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
744 } 925 }
745 return false; 926 m_items.LockItemsForWrite(false);
746 927
928 return false;
747 } 929 }
748 930
749 /// <summary> 931 /// <summary>
@@ -754,43 +936,59 @@ namespace OpenSim.Region.Framework.Scenes
754 /// in this prim's inventory.</returns> 936 /// in this prim's inventory.</returns>
755 public int RemoveInventoryItem(UUID itemID) 937 public int RemoveInventoryItem(UUID itemID)
756 { 938 {
757 TaskInventoryItem item = GetInventoryItem(itemID); 939 m_items.LockItemsForRead(true);
758 if (item != null) 940
941 if (m_items.ContainsKey(itemID))
759 { 942 {
760 int type = m_items[itemID].InvType; 943 int type = m_items[itemID].InvType;
944 m_items.LockItemsForRead(false);
761 if (type == 10) // Script 945 if (type == 10) // Script
762 { 946 {
763 m_part.RemoveScriptEvents(itemID);
764 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID); 947 m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemID);
765 } 948 }
949 m_items.LockItemsForWrite(true);
766 m_items.Remove(itemID); 950 m_items.Remove(itemID);
951 m_items.LockItemsForWrite(false);
767 m_inventorySerial++; 952 m_inventorySerial++;
768 m_part.TriggerScriptChangedEvent(Changed.INVENTORY); 953 m_part.TriggerScriptChangedEvent(Changed.INVENTORY);
769 954
770 HasInventoryChanged = true; 955 HasInventoryChanged = true;
771 m_part.ParentGroup.HasGroupChanged = true; 956 m_part.ParentGroup.HasGroupChanged = true;
772 957
773 if (!ContainsScripts()) 958 int scriptcount = 0;
959 m_items.LockItemsForRead(true);
960 foreach (TaskInventoryItem item in m_items.Values)
961 {
962 if (item.Type == 10)
963 {
964 scriptcount++;
965 }
966 }
967 m_items.LockItemsForRead(false);
968
969
970 if (scriptcount <= 0)
971 {
774 m_part.RemFlag(PrimFlags.Scripted); 972 m_part.RemFlag(PrimFlags.Scripted);
973 }
775 974
776 m_part.ScheduleFullUpdate(); 975 m_part.ScheduleFullUpdate();
777 976
778 return type; 977 return type;
779
780 } 978 }
781 else 979 else
782 { 980 {
981 m_items.LockItemsForRead(false);
783 m_log.ErrorFormat( 982 m_log.ErrorFormat(
784 "[PRIM INVENTORY]: " + 983 "[PRIM INVENTORY]: " +
785 "Tried to remove item ID {0} from prim {1}, {2} at {3} in {4} but the item does not exist in this inventory", 984 "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory",
786 itemID, m_part.Name, m_part.UUID, 985 itemID, m_part.Name, m_part.UUID);
787 m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName);
788 } 986 }
789 987
790 return -1; 988 return -1;
791 } 989 }
792 990
793 private bool CreateInventoryFile() 991 private bool CreateInventoryFileName()
794 { 992 {
795// m_log.DebugFormat( 993// m_log.DebugFormat(
796// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}", 994// "[PRIM INVENTORY]: Creating inventory file for {0} {1} {2}, serial {3}",
@@ -799,116 +997,125 @@ namespace OpenSim.Region.Framework.Scenes
799 if (m_inventoryFileName == String.Empty || 997 if (m_inventoryFileName == String.Empty ||
800 m_inventoryFileNameSerial < m_inventorySerial) 998 m_inventoryFileNameSerial < m_inventorySerial)
801 { 999 {
802 // Something changed, we need to create a new file
803 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; 1000 m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp";
804 m_inventoryFileNameSerial = m_inventorySerial; 1001 m_inventoryFileNameSerial = m_inventorySerial;
805 1002
806 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); 1003 return true;
1004 }
1005
1006 return false;
1007 }
1008
1009 /// <summary>
1010 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
1011 /// </summary>
1012 /// <param name="xferManager"></param>
1013 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
1014 {
1015 bool changed = CreateInventoryFileName();
1016
1017 bool includeAssets = false;
1018 if (m_part.ParentGroup.Scene.Permissions.CanEditObjectInventory(m_part.UUID, client.AgentId))
1019 includeAssets = true;
1020
1021 if (m_inventoryPrivileged != includeAssets)
1022 changed = true;
1023
1024 InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero);
807 1025
808 lock (m_items) 1026 Items.LockItemsForRead(true);
1027
1028 if (m_inventorySerial == 0) // No inventory
1029 {
1030 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1031 Items.LockItemsForRead(false);
1032 return;
1033 }
1034
1035 if (m_items.Count == 0) // No inventory
1036 {
1037 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
1038 Items.LockItemsForRead(false);
1039 return;
1040 }
1041
1042 if (!changed)
1043 {
1044 if (m_inventoryFileData.Length > 2)
809 { 1045 {
810 foreach (TaskInventoryItem item in m_items.Values) 1046 xferManager.AddNewFile(m_inventoryFileName,
811 { 1047 m_inventoryFileData);
812// m_log.DebugFormat( 1048 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
813// "[PRIM INVENTORY]: Adding item {0} {1} for serial {2} on prim {3} {4} {5}", 1049 Util.StringToBytes256(m_inventoryFileName));
814// item.Name, item.ItemID, m_inventorySerial, m_part.Name, m_part.UUID, m_part.LocalId);
815 1050
816 UUID ownerID = item.OwnerID; 1051 Items.LockItemsForRead(false);
817 uint everyoneMask = 0; 1052 return;
818 uint baseMask = item.BasePermissions; 1053 }
819 uint ownerMask = item.CurrentPermissions; 1054 }
820 uint groupMask = item.GroupPermissions;
821 1055
822 invString.AddItemStart(); 1056 m_inventoryPrivileged = includeAssets;
823 invString.AddNameValueLine("item_id", item.ItemID.ToString());
824 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
825 1057
826 invString.AddPermissionsStart(); 1058 foreach (TaskInventoryItem item in m_items.Values)
1059 {
1060 UUID ownerID = item.OwnerID;
1061 uint everyoneMask = 0;
1062 uint baseMask = item.BasePermissions;
1063 uint ownerMask = item.CurrentPermissions;
1064 uint groupMask = item.GroupPermissions;
827 1065
828 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); 1066 invString.AddItemStart();
829 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); 1067 invString.AddNameValueLine("item_id", item.ItemID.ToString());
830 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask)); 1068 invString.AddNameValueLine("parent_id", m_part.UUID.ToString());
831 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
832 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
833 1069
834 invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); 1070 invString.AddPermissionsStart();
835 invString.AddNameValueLine("owner_id", ownerID.ToString());
836 1071
837 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); 1072 invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask));
1073 invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask));
1074 invString.AddNameValueLine("group_mask", Utils.UIntToHexString(groupMask));
1075 invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask));
1076 invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions));
838 1077
839 invString.AddNameValueLine("group_id", item.GroupID.ToString()); 1078 invString.AddNameValueLine("creator_id", item.CreatorID.ToString());
840 invString.AddSectionEnd(); 1079 invString.AddNameValueLine("owner_id", ownerID.ToString());
841 1080
842 invString.AddNameValueLine("asset_id", item.AssetID.ToString()); 1081 invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString());
843 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
844 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
845 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
846 1082
847 invString.AddSaleStart(); 1083 invString.AddNameValueLine("group_id", item.GroupID.ToString());
848 invString.AddNameValueLine("sale_type", "not"); 1084 invString.AddSectionEnd();
849 invString.AddNameValueLine("sale_price", "0");
850 invString.AddSectionEnd();
851 1085
852 invString.AddNameValueLine("name", item.Name + "|"); 1086 if (includeAssets)
853 invString.AddNameValueLine("desc", item.Description + "|"); 1087 invString.AddNameValueLine("asset_id", item.AssetID.ToString());
1088 else
1089 invString.AddNameValueLine("asset_id", UUID.Zero.ToString());
1090 invString.AddNameValueLine("type", Utils.AssetTypeToString((AssetType)item.Type));
1091 invString.AddNameValueLine("inv_type", Utils.InventoryTypeToString((InventoryType)item.InvType));
1092 invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags));
854 1093
855 invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); 1094 invString.AddSaleStart();
856 invString.AddSectionEnd(); 1095 invString.AddNameValueLine("sale_type", "not");
857 } 1096 invString.AddNameValueLine("sale_price", "0");
858 } 1097 invString.AddSectionEnd();
859 1098
860 m_inventoryFileData = Utils.StringToBytes(invString.BuildString); 1099 invString.AddNameValueLine("name", item.Name + "|");
1100 invString.AddNameValueLine("desc", item.Description + "|");
861 1101
862 return true; 1102 invString.AddNameValueLine("creation_date", item.CreationDate.ToString());
1103 invString.AddSectionEnd();
863 } 1104 }
864 1105
865 // No need to recreate, the existing file is fine 1106 Items.LockItemsForRead(false);
866 return false;
867 }
868 1107
869 /// <summary> 1108 m_inventoryFileData = Utils.StringToBytes(invString.BuildString);
870 /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client
871 /// </summary>
872 /// <param name="xferManager"></param>
873 public void RequestInventoryFile(IClientAPI client, IXfer xferManager)
874 {
875 lock (m_items)
876 {
877 // Don't send a inventory xfer name if there are no items. Doing so causes viewer 3 to crash when rezzing
878 // a new script if any previous deletion has left the prim inventory empty.
879 if (m_items.Count == 0) // No inventory
880 {
881// m_log.DebugFormat(
882// "[PRIM INVENTORY]: Not sending inventory data for part {0} {1} {2} for {3} since no items",
883// m_part.Name, m_part.LocalId, m_part.UUID, client.Name);
884
885 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
886 return;
887 }
888 1109
889 CreateInventoryFile(); 1110 if (m_inventoryFileData.Length > 2)
890 1111 {
891 // In principle, we should only do the rest if the inventory changed; 1112 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
892 // by sending m_inventorySerial to the client, it ought to know 1113 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
893 // that nothing changed and that it doesn't need to request the file. 1114 Util.StringToBytes256(m_inventoryFileName));
894 // Unfortunately, it doesn't look like the client optimizes this; 1115 return;
895 // the client seems to always come back and request the Xfer,
896 // no matter what value m_inventorySerial has.
897 // FIXME: Could probably be > 0 here rather than > 2
898 if (m_inventoryFileData.Length > 2)
899 {
900 // Add the file for Xfer
901 // m_log.DebugFormat(
902 // "[PRIM INVENTORY]: Adding inventory file {0} (length {1}) for transfer on {2} {3} {4}",
903 // m_inventoryFileName, m_inventoryFileData.Length, m_part.Name, m_part.UUID, m_part.LocalId);
904
905 xferManager.AddNewFile(m_inventoryFileName, m_inventoryFileData);
906 }
907
908 // Tell the client we're ready to Xfer the file
909 client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial,
910 Util.StringToBytes256(m_inventoryFileName));
911 } 1116 }
1117
1118 client.SendTaskInventory(m_part.UUID, 0, new byte[0]);
912 } 1119 }
913 1120
914 /// <summary> 1121 /// <summary>
@@ -917,13 +1124,19 @@ namespace OpenSim.Region.Framework.Scenes
917 /// <param name="datastore"></param> 1124 /// <param name="datastore"></param>
918 public void ProcessInventoryBackup(ISimulationDataService datastore) 1125 public void ProcessInventoryBackup(ISimulationDataService datastore)
919 { 1126 {
920 if (HasInventoryChanged) 1127// Removed this because linking will cause an immediate delete of the new
921 { 1128// child prim from the database and the subsequent storing of the prim sees
922 HasInventoryChanged = false; 1129// the inventory of it as unchanged and doesn't store it at all. The overhead
923 List<TaskInventoryItem> items = GetInventoryItems(); 1130// of storing prim inventory needlessly is much less than the aggravation
924 datastore.StorePrimInventory(m_part.UUID, items); 1131// of prim inventory loss.
1132// if (HasInventoryChanged)
1133// {
1134 Items.LockItemsForRead(true);
1135 datastore.StorePrimInventory(m_part.UUID, Items.Values);
1136 Items.LockItemsForRead(false);
925 1137
926 } 1138 HasInventoryChanged = false;
1139// }
927 } 1140 }
928 1141
929 public class InventoryStringBuilder 1142 public class InventoryStringBuilder
@@ -989,87 +1202,63 @@ namespace OpenSim.Region.Framework.Scenes
989 { 1202 {
990 uint mask=0x7fffffff; 1203 uint mask=0x7fffffff;
991 1204
992 lock (m_items) 1205 foreach (TaskInventoryItem item in m_items.Values)
993 { 1206 {
994 foreach (TaskInventoryItem item in m_items.Values) 1207 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1208 mask &= ~((uint)PermissionMask.Copy >> 13);
1209 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1210 mask &= ~((uint)PermissionMask.Transfer >> 13);
1211 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1212 mask &= ~((uint)PermissionMask.Modify >> 13);
1213
1214 if (item.InvType == (int)InventoryType.Object)
995 { 1215 {
996 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) 1216 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
997 mask &= ~((uint)PermissionMask.Copy >> 13); 1217 mask &= ~((uint)PermissionMask.Copy >> 13);
998 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) 1218 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
999 mask &= ~((uint)PermissionMask.Transfer >> 13); 1219 mask &= ~((uint)PermissionMask.Transfer >> 13);
1000 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) 1220 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1001 mask &= ~((uint)PermissionMask.Modify >> 13); 1221 mask &= ~((uint)PermissionMask.Modify >> 13);
1002
1003 if (item.InvType != (int)InventoryType.Object)
1004 {
1005 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0)
1006 mask &= ~((uint)PermissionMask.Copy >> 13);
1007 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0)
1008 mask &= ~((uint)PermissionMask.Transfer >> 13);
1009 if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0)
1010 mask &= ~((uint)PermissionMask.Modify >> 13);
1011 }
1012 else
1013 {
1014 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1015 mask &= ~((uint)PermissionMask.Copy >> 13);
1016 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1017 mask &= ~((uint)PermissionMask.Transfer >> 13);
1018 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1019 mask &= ~((uint)PermissionMask.Modify >> 13);
1020 }
1021
1022 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1023 mask &= ~(uint)PermissionMask.Copy;
1024 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1025 mask &= ~(uint)PermissionMask.Transfer;
1026 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1027 mask &= ~(uint)PermissionMask.Modify;
1028 } 1222 }
1223
1224 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
1225 mask &= ~(uint)PermissionMask.Copy;
1226 if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)
1227 mask &= ~(uint)PermissionMask.Transfer;
1228 if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0)
1229 mask &= ~(uint)PermissionMask.Modify;
1029 } 1230 }
1030
1031 return mask; 1231 return mask;
1032 } 1232 }
1033 1233
1034 public void ApplyNextOwnerPermissions() 1234 public void ApplyNextOwnerPermissions()
1035 { 1235 {
1036 lock (m_items) 1236 foreach (TaskInventoryItem item in m_items.Values)
1037 { 1237 {
1038 foreach (TaskInventoryItem item in m_items.Values) 1238 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0)
1039 { 1239 {
1040// m_log.DebugFormat ( 1240 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1041// "[SCENE OBJECT PART INVENTORY]: Applying next permissions {0} to {1} in {2} with current {3}, base {4}, everyone {5}", 1241 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1042// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions); 1242 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1043 1243 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1044 if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) 1244 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1045 { 1245 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1046 if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0)
1047 item.CurrentPermissions &= ~(uint)PermissionMask.Copy;
1048 if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0)
1049 item.CurrentPermissions &= ~(uint)PermissionMask.Transfer;
1050 if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0)
1051 item.CurrentPermissions &= ~(uint)PermissionMask.Modify;
1052 }
1053
1054 item.CurrentPermissions &= item.NextPermissions;
1055 item.BasePermissions &= item.NextPermissions;
1056 item.EveryonePermissions &= item.NextPermissions;
1057 item.OwnerChanged = true;
1058 item.PermsMask = 0;
1059 item.PermsGranter = UUID.Zero;
1060 } 1246 }
1247 item.CurrentPermissions &= item.NextPermissions;
1248 item.BasePermissions &= item.NextPermissions;
1249 item.EveryonePermissions &= item.NextPermissions;
1250 item.OwnerChanged = true;
1251 item.PermsMask = 0;
1252 item.PermsGranter = UUID.Zero;
1061 } 1253 }
1062 } 1254 }
1063 1255
1064 public void ApplyGodPermissions(uint perms) 1256 public void ApplyGodPermissions(uint perms)
1065 { 1257 {
1066 lock (m_items) 1258 foreach (TaskInventoryItem item in m_items.Values)
1067 { 1259 {
1068 foreach (TaskInventoryItem item in m_items.Values) 1260 item.CurrentPermissions = perms;
1069 { 1261 item.BasePermissions = perms;
1070 item.CurrentPermissions = perms;
1071 item.BasePermissions = perms;
1072 }
1073 } 1262 }
1074 1263
1075 m_inventorySerial++; 1264 m_inventorySerial++;
@@ -1082,14 +1271,11 @@ namespace OpenSim.Region.Framework.Scenes
1082 /// <returns></returns> 1271 /// <returns></returns>
1083 public bool ContainsScripts() 1272 public bool ContainsScripts()
1084 { 1273 {
1085 lock (m_items) 1274 foreach (TaskInventoryItem item in m_items.Values)
1086 { 1275 {
1087 foreach (TaskInventoryItem item in m_items.Values) 1276 if (item.InvType == (int)InventoryType.LSL)
1088 { 1277 {
1089 if (item.InvType == (int)InventoryType.LSL) 1278 return true;
1090 {
1091 return true;
1092 }
1093 } 1279 }
1094 } 1280 }
1095 1281
@@ -1103,17 +1289,15 @@ namespace OpenSim.Region.Framework.Scenes
1103 public int ScriptCount() 1289 public int ScriptCount()
1104 { 1290 {
1105 int count = 0; 1291 int count = 0;
1106 lock (m_items) 1292 Items.LockItemsForRead(true);
1293 foreach (TaskInventoryItem item in m_items.Values)
1107 { 1294 {
1108 foreach (TaskInventoryItem item in m_items.Values) 1295 if (item.InvType == (int)InventoryType.LSL)
1109 { 1296 {
1110 if (item.InvType == (int)InventoryType.LSL) 1297 count++;
1111 {
1112 count++;
1113 }
1114 } 1298 }
1115 } 1299 }
1116 1300 Items.LockItemsForRead(false);
1117 return count; 1301 return count;
1118 } 1302 }
1119 /// <summary> 1303 /// <summary>
@@ -1149,11 +1333,8 @@ namespace OpenSim.Region.Framework.Scenes
1149 { 1333 {
1150 List<UUID> ret = new List<UUID>(); 1334 List<UUID> ret = new List<UUID>();
1151 1335
1152 lock (m_items) 1336 foreach (TaskInventoryItem item in m_items.Values)
1153 { 1337 ret.Add(item.ItemID);
1154 foreach (TaskInventoryItem item in m_items.Values)
1155 ret.Add(item.ItemID);
1156 }
1157 1338
1158 return ret; 1339 return ret;
1159 } 1340 }
@@ -1162,8 +1343,9 @@ namespace OpenSim.Region.Framework.Scenes
1162 { 1343 {
1163 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1344 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1164 1345
1165 lock (m_items) 1346 Items.LockItemsForRead(true);
1166 ret = new List<TaskInventoryItem>(m_items.Values); 1347 ret = new List<TaskInventoryItem>(m_items.Values);
1348 Items.LockItemsForRead(false);
1167 1349
1168 return ret; 1350 return ret;
1169 } 1351 }
@@ -1172,18 +1354,24 @@ namespace OpenSim.Region.Framework.Scenes
1172 { 1354 {
1173 List<TaskInventoryItem> ret = new List<TaskInventoryItem>(); 1355 List<TaskInventoryItem> ret = new List<TaskInventoryItem>();
1174 1356
1175 lock (m_items) 1357 Items.LockItemsForRead(true);
1176 { 1358
1177 foreach (TaskInventoryItem item in m_items.Values) 1359 foreach (TaskInventoryItem item in m_items.Values)
1178 if (item.InvType == (int)type) 1360 if (item.InvType == (int)type)
1179 ret.Add(item); 1361 ret.Add(item);
1180 } 1362
1363 Items.LockItemsForRead(false);
1181 1364
1182 return ret; 1365 return ret;
1183 } 1366 }
1184 1367
1185 public Dictionary<UUID, string> GetScriptStates() 1368 public Dictionary<UUID, string> GetScriptStates()
1186 { 1369 {
1370 return GetScriptStates(false);
1371 }
1372
1373 public Dictionary<UUID, string> GetScriptStates(bool oldIDs)
1374 {
1187 Dictionary<UUID, string> ret = new Dictionary<UUID, string>(); 1375 Dictionary<UUID, string> ret = new Dictionary<UUID, string>();
1188 1376
1189 if (m_part.ParentGroup.Scene == null) // Group not in a scene 1377 if (m_part.ParentGroup.Scene == null) // Group not in a scene
@@ -1205,14 +1393,21 @@ namespace OpenSim.Region.Framework.Scenes
1205 string n = e.GetXMLState(item.ItemID); 1393 string n = e.GetXMLState(item.ItemID);
1206 if (n != String.Empty) 1394 if (n != String.Empty)
1207 { 1395 {
1208 if (!ret.ContainsKey(item.ItemID)) 1396 if (oldIDs)
1209 ret[item.ItemID] = n; 1397 {
1398 if (!ret.ContainsKey(item.OldItemID))
1399 ret[item.OldItemID] = n;
1400 }
1401 else
1402 {
1403 if (!ret.ContainsKey(item.ItemID))
1404 ret[item.ItemID] = n;
1405 }
1210 break; 1406 break;
1211 } 1407 }
1212 } 1408 }
1213 } 1409 }
1214 } 1410 }
1215
1216 return ret; 1411 return ret;
1217 } 1412 }
1218 1413
@@ -1245,4 +1440,4 @@ namespace OpenSim.Region.Framework.Scenes
1245 } 1440 }
1246 } 1441 }
1247 } 1442 }
1248} \ No newline at end of file 1443}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 3adafc1..07b36b3 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -63,6 +63,7 @@ namespace OpenSim.Region.Framework.Scenes
63 63
64 struct ScriptControllers 64 struct ScriptControllers
65 { 65 {
66 public UUID objectID;
66 public UUID itemID; 67 public UUID itemID;
67 public ScriptControlled ignoreControls; 68 public ScriptControlled ignoreControls;
68 public ScriptControlled eventControls; 69 public ScriptControlled eventControls;
@@ -98,7 +99,7 @@ namespace OpenSim.Region.Framework.Scenes
98 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis 99 /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
99 /// issue #1716 100 /// issue #1716
100 /// </summary> 101 /// </summary>
101 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); 102 public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f);
102 103
103 /// <summary> 104 /// <summary>
104 /// Movement updates for agents in neighboring regions are sent directly to clients. 105 /// Movement updates for agents in neighboring regions are sent directly to clients.
@@ -175,6 +176,7 @@ namespace OpenSim.Region.Framework.Scenes
175// private int m_lastColCount = -1; //KF: Look for Collision chnages 176// private int m_lastColCount = -1; //KF: Look for Collision chnages
176// private int m_updateCount = 0; //KF: Update Anims for a while 177// private int m_updateCount = 0; //KF: Update Anims for a while
177// private static readonly int UPDATE_COUNT = 10; // how many frames to update for 178// private static readonly int UPDATE_COUNT = 10; // how many frames to update for
179 private List<uint> m_lastColliders = new List<uint>();
178 180
179 private TeleportFlags m_teleportFlags; 181 private TeleportFlags m_teleportFlags;
180 public TeleportFlags TeleportFlags 182 public TeleportFlags TeleportFlags
@@ -236,6 +238,13 @@ namespace OpenSim.Region.Framework.Scenes
236 //private int m_moveToPositionStateStatus; 238 //private int m_moveToPositionStateStatus;
237 //***************************************************** 239 //*****************************************************
238 240
241 private bool m_collisionEventFlag = false;
242 private object m_collisionEventLock = new Object();
243
244 private int m_movementAnimationUpdateCounter = 0;
245
246 private Vector3 m_prevSitOffset;
247
239 protected AvatarAppearance m_appearance; 248 protected AvatarAppearance m_appearance;
240 249
241 public AvatarAppearance Appearance 250 public AvatarAppearance Appearance
@@ -577,6 +586,13 @@ namespace OpenSim.Region.Framework.Scenes
577 /// </summary> 586 /// </summary>
578 public uint ParentID { get; set; } 587 public uint ParentID { get; set; }
579 588
589 public UUID ParentUUID
590 {
591 get { return m_parentUUID; }
592 set { m_parentUUID = value; }
593 }
594 private UUID m_parentUUID = UUID.Zero;
595
580 /// <summary> 596 /// <summary>
581 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null. 597 /// If the avatar is sitting, the prim that it's sitting on. If not sitting then null.
582 /// </summary> 598 /// </summary>
@@ -737,6 +753,33 @@ namespace OpenSim.Region.Framework.Scenes
737 Appearance = appearance; 753 Appearance = appearance;
738 } 754 }
739 755
756 private void RegionHeartbeatEnd(Scene scene)
757 {
758 if (IsChildAgent)
759 return;
760
761 m_movementAnimationUpdateCounter ++;
762 if (m_movementAnimationUpdateCounter >= 2)
763 {
764 m_movementAnimationUpdateCounter = 0;
765 if (Animator != null)
766 {
767 // If the parentID == 0 we are not sitting
768 // if !SitGournd then we are not sitting on the ground
769 // Fairly straightforward, now here comes the twist
770 // if ParentUUID is NOT UUID.Zero, we are looking to
771 // be sat on an object that isn't there yet. Should
772 // be treated as if sat.
773 if(ParentID == 0 && !SitGround && ParentUUID == UUID.Zero) // skip it if sitting
774 Animator.UpdateMovementAnimations();
775 }
776 else
777 {
778 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
779 }
780 }
781 }
782
740 public void RegisterToEvents() 783 public void RegisterToEvents()
741 { 784 {
742 ControllingClient.OnCompleteMovementToRegion += CompleteMovement; 785 ControllingClient.OnCompleteMovementToRegion += CompleteMovement;
@@ -746,6 +789,7 @@ namespace OpenSim.Region.Framework.Scenes
746 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun; 789 ControllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
747 ControllingClient.OnStartAnim += HandleStartAnim; 790 ControllingClient.OnStartAnim += HandleStartAnim;
748 ControllingClient.OnStopAnim += HandleStopAnim; 791 ControllingClient.OnStopAnim += HandleStopAnim;
792 ControllingClient.OnChangeAnim += avnHandleChangeAnim;
749 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls; 793 ControllingClient.OnForceReleaseControls += HandleForceReleaseControls;
750 ControllingClient.OnAutoPilotGo += MoveToTarget; 794 ControllingClient.OnAutoPilotGo += MoveToTarget;
751 795
@@ -806,10 +850,38 @@ namespace OpenSim.Region.Framework.Scenes
806 "[SCENE]: Upgrading child to root agent for {0} in {1}", 850 "[SCENE]: Upgrading child to root agent for {0} in {1}",
807 Name, m_scene.RegionInfo.RegionName); 851 Name, m_scene.RegionInfo.RegionName);
808 852
809 //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
810
811 bool wasChild = IsChildAgent; 853 bool wasChild = IsChildAgent;
812 IsChildAgent = false; 854
855 if (ParentUUID != UUID.Zero)
856 {
857 m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID);
858 SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID);
859 if (part == null)
860 {
861 m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID);
862 }
863 else
864 {
865 part.ParentGroup.AddAvatar(UUID);
866 if (part.SitTargetPosition != Vector3.Zero)
867 part.SitTargetAvatar = UUID;
868 ParentPosition = part.GetWorldPosition();
869 ParentID = part.LocalId;
870 ParentPart = part;
871 m_pos = m_prevSitOffset;
872 pos = ParentPosition;
873 }
874 ParentUUID = UUID.Zero;
875
876 IsChildAgent = false;
877
878 Animator.TrySetMovementAnimation("SIT");
879 }
880 else
881 {
882 IsChildAgent = false;
883 }
884
813 885
814 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>(); 886 IGroupsModule gm = m_scene.RequestModuleInterface<IGroupsModule>();
815 if (gm != null) 887 if (gm != null)
@@ -819,62 +891,72 @@ namespace OpenSim.Region.Framework.Scenes
819 891
820 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); 892 m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
821 893
822 // Moved this from SendInitialData to ensure that Appearance is initialized 894 if (ParentID == 0)
823 // before the inventory is processed in MakeRootAgent. This fixes a race condition
824 // related to the handling of attachments
825 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
826 if (m_scene.TestBorderCross(pos, Cardinals.E))
827 { 895 {
828 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); 896 // Moved this from SendInitialData to ensure that Appearance is initialized
829 pos.X = crossedBorder.BorderLine.Z - 1; 897 // before the inventory is processed in MakeRootAgent. This fixes a race condition
830 } 898 // related to the handling of attachments
899 //m_scene.GetAvatarAppearance(ControllingClient, out Appearance);
900 if (m_scene.TestBorderCross(pos, Cardinals.E))
901 {
902 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
903 pos.X = crossedBorder.BorderLine.Z - 1;
904 }
831 905
832 if (m_scene.TestBorderCross(pos, Cardinals.N)) 906 if (m_scene.TestBorderCross(pos, Cardinals.N))
833 { 907 {
834 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); 908 Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
835 pos.Y = crossedBorder.BorderLine.Z - 1; 909 pos.Y = crossedBorder.BorderLine.Z - 1;
836 } 910 }
837 911
838 CheckAndAdjustLandingPoint(ref pos); 912 CheckAndAdjustLandingPoint(ref pos);
839 913
840 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) 914 if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
841 { 915 {
842 m_log.WarnFormat( 916 m_log.WarnFormat(
843 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", 917 "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
844 pos, Name, UUID); 918 pos, Name, UUID);
845 919
846 if (pos.X < 0f) pos.X = 0f; 920 if (pos.X < 0f) pos.X = 0f;
847 if (pos.Y < 0f) pos.Y = 0f; 921 if (pos.Y < 0f) pos.Y = 0f;
848 if (pos.Z < 0f) pos.Z = 0f; 922 if (pos.Z < 0f) pos.Z = 0f;
849 } 923 }
850 924
851 float localAVHeight = 1.56f; 925 float localAVHeight = 1.56f;
852 if (Appearance.AvatarHeight > 0) 926 if (Appearance.AvatarHeight > 0)
853 localAVHeight = Appearance.AvatarHeight; 927 localAVHeight = Appearance.AvatarHeight;
854 928
855 float posZLimit = 0; 929 float posZLimit = 0;
856 930
857 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) 931 if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
858 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; 932 posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
859 933
860 float newPosZ = posZLimit + localAVHeight / 2; 934 float newPosZ = posZLimit + localAVHeight / 2;
861 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) 935 if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
862 { 936 {
863 pos.Z = newPosZ; 937 pos.Z = newPosZ;
864 } 938 }
865 AbsolutePosition = pos; 939 AbsolutePosition = pos;
866 940
867 AddToPhysicalScene(isFlying); 941 if (m_teleportFlags == TeleportFlags.Default)
942 {
943 Vector3 vel = Velocity;
944 AddToPhysicalScene(isFlying);
945 if (PhysicsActor != null)
946 PhysicsActor.SetMomentum(vel);
947 }
948 else
949 AddToPhysicalScene(isFlying);
868 950
869 if (ForceFly) 951 if (ForceFly)
870 { 952 {
871 Flying = true; 953 Flying = true;
872 } 954 }
873 else if (FlyDisabled) 955 else if (FlyDisabled)
874 { 956 {
875 Flying = false; 957 Flying = false;
958 }
876 } 959 }
877
878 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying 960 // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
879 // avatar to return to the standing position in mid-air. On login it looks like this is being sent 961 // avatar to return to the standing position in mid-air. On login it looks like this is being sent
880 // elsewhere anyway 962 // elsewhere anyway
@@ -892,14 +974,19 @@ namespace OpenSim.Region.Framework.Scenes
892 { 974 {
893 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); 975 m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments...");
894 // Resume scripts 976 // Resume scripts
895 foreach (SceneObjectGroup sog in m_attachments) 977 Util.FireAndForget(delegate(object x) {
896 { 978 foreach (SceneObjectGroup sog in m_attachments)
897 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); 979 {
898 sog.ResumeScripts(); 980 sog.ScheduleGroupForFullUpdate();
899 } 981 sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource());
982 sog.ResumeScripts();
983 }
984 });
900 } 985 }
901 } 986 }
902 987
988 SendAvatarDataToAllAgents();
989
903 // send the animations of the other presences to me 990 // send the animations of the other presences to me
904 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) 991 m_scene.ForEachRootScenePresence(delegate(ScenePresence presence)
905 { 992 {
@@ -910,9 +997,12 @@ namespace OpenSim.Region.Framework.Scenes
910 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will 997 // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will
911 // stall on the border crossing since the existing child agent will still have the last movement 998 // stall on the border crossing since the existing child agent will still have the last movement
912 // recorded, which stops the input from being processed. 999 // recorded, which stops the input from being processed.
1000
913 MovementFlag = 0; 1001 MovementFlag = 0;
914 1002
915 m_scene.EventManager.TriggerOnMakeRootAgent(this); 1003 m_scene.EventManager.TriggerOnMakeRootAgent(this);
1004
1005 m_scene.EventManager.OnRegionHeartbeatEnd += RegionHeartbeatEnd;
916 } 1006 }
917 1007
918 public int GetStateSource() 1008 public int GetStateSource()
@@ -940,12 +1030,16 @@ namespace OpenSim.Region.Framework.Scenes
940 /// </remarks> 1030 /// </remarks>
941 public void MakeChildAgent() 1031 public void MakeChildAgent()
942 { 1032 {
1033 m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd;
1034
943 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); 1035 m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName);
944 1036
945 // Reset these so that teleporting in and walking out isn't seen 1037 // Reset these so that teleporting in and walking out isn't seen
946 // as teleporting back 1038 // as teleporting back
947 TeleportFlags = TeleportFlags.Default; 1039 TeleportFlags = TeleportFlags.Default;
948 1040
1041 MovementFlag = 0;
1042
949 // It looks like Animator is set to null somewhere, and MakeChild 1043 // It looks like Animator is set to null somewhere, and MakeChild
950 // is called after that. Probably in aborted teleports. 1044 // is called after that. Probably in aborted teleports.
951 if (Animator == null) 1045 if (Animator == null)
@@ -953,6 +1047,7 @@ namespace OpenSim.Region.Framework.Scenes
953 else 1047 else
954 Animator.ResetAnimations(); 1048 Animator.ResetAnimations();
955 1049
1050
956// m_log.DebugFormat( 1051// m_log.DebugFormat(
957// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", 1052// "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
958// Name, UUID, m_scene.RegionInfo.RegionName); 1053// Name, UUID, m_scene.RegionInfo.RegionName);
@@ -979,9 +1074,9 @@ namespace OpenSim.Region.Framework.Scenes
979 { 1074 {
980// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; 1075// PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
981 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; 1076 PhysicsActor.OnOutOfBounds -= OutOfBoundsCall;
982 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
983 PhysicsActor.UnSubscribeEvents();
984 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; 1077 PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
1078 PhysicsActor.UnSubscribeEvents();
1079 m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
985 PhysicsActor = null; 1080 PhysicsActor = null;
986 } 1081 }
987// else 1082// else
@@ -998,7 +1093,7 @@ namespace OpenSim.Region.Framework.Scenes
998 /// <param name="pos"></param> 1093 /// <param name="pos"></param>
999 public void Teleport(Vector3 pos) 1094 public void Teleport(Vector3 pos)
1000 { 1095 {
1001 TeleportWithMomentum(pos, null); 1096 TeleportWithMomentum(pos, Vector3.Zero);
1002 } 1097 }
1003 1098
1004 public void TeleportWithMomentum(Vector3 pos, Vector3? v) 1099 public void TeleportWithMomentum(Vector3 pos, Vector3? v)
@@ -1022,6 +1117,41 @@ namespace OpenSim.Region.Framework.Scenes
1022 SendTerseUpdateToAllClients(); 1117 SendTerseUpdateToAllClients();
1023 } 1118 }
1024 1119
1120 public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY)
1121 {
1122 CheckLandingPoint(ref newpos);
1123 AbsolutePosition = newpos;
1124
1125 if (newvel.HasValue)
1126 {
1127 if ((Vector3)newvel == Vector3.Zero)
1128 {
1129 if (PhysicsActor != null)
1130 PhysicsActor.SetMomentum(Vector3.Zero);
1131 m_velocity = Vector3.Zero;
1132 }
1133 else
1134 {
1135 if (PhysicsActor != null)
1136 PhysicsActor.SetMomentum((Vector3)newvel);
1137 m_velocity = (Vector3)newvel;
1138
1139 if (rotateToVelXY)
1140 {
1141 Vector3 lookAt = (Vector3)newvel;
1142 lookAt.Z = 0;
1143 lookAt.Normalize();
1144 ControllingClient.SendLocalTeleport(newpos, lookAt, (uint)TeleportFlags.ViaLocation);
1145 return;
1146 }
1147 }
1148 }
1149
1150 SendTerseUpdateToAllClients();
1151 }
1152
1153
1154
1025 public void StopFlying() 1155 public void StopFlying()
1026 { 1156 {
1027 ControllingClient.StopFlying(this); 1157 ControllingClient.StopFlying(this);
@@ -1337,8 +1467,18 @@ namespace OpenSim.Region.Framework.Scenes
1337 { 1467 {
1338 if (m_followCamAuto) 1468 if (m_followCamAuto)
1339 { 1469 {
1340 Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT; 1470 // Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
1341 m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback); 1471 // m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(CameraPosition - posAdjusted), Vector3.Distance(CameraPosition, posAdjusted) + 0.3f, RayCastCameraCallback);
1472
1473 Vector3 posAdjusted = AbsolutePosition + HEAD_ADJUSTMENT;
1474 Vector3 distTocam = CameraPosition - posAdjusted;
1475 float distTocamlen = distTocam.Length();
1476 if (distTocamlen > 0)
1477 {
1478 distTocam *= 1.0f / distTocamlen;
1479 m_scene.PhysicsScene.RaycastWorld(posAdjusted, distTocam, distTocamlen + 0.3f, RayCastCameraCallback);
1480 }
1481
1342 } 1482 }
1343 } 1483 }
1344 1484
@@ -1772,12 +1912,17 @@ namespace OpenSim.Region.Framework.Scenes
1772// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name); 1912// m_log.DebugFormat("[SCENE PRESENCE]: StandUp() for {0}", Name);
1773 1913
1774 SitGround = false; 1914 SitGround = false;
1915
1916/* move this down so avatar gets physical in the new position and not where it is siting
1775 if (PhysicsActor == null) 1917 if (PhysicsActor == null)
1776 AddToPhysicalScene(false); 1918 AddToPhysicalScene(false);
1919 */
1777 1920
1778 if (ParentID != 0) 1921 if (ParentID != 0)
1779 { 1922 {
1780 SceneObjectPart part = ParentPart; 1923 SceneObjectPart part = ParentPart;
1924 UnRegisterSeatControls(part.ParentGroup.UUID);
1925
1781 TaskInventoryDictionary taskIDict = part.TaskInventory; 1926 TaskInventoryDictionary taskIDict = part.TaskInventory;
1782 if (taskIDict != null) 1927 if (taskIDict != null)
1783 { 1928 {
@@ -1797,6 +1942,7 @@ namespace OpenSim.Region.Framework.Scenes
1797 if (part.SitTargetAvatar == UUID) 1942 if (part.SitTargetAvatar == UUID)
1798 part.SitTargetAvatar = UUID.Zero; 1943 part.SitTargetAvatar = UUID.Zero;
1799 1944
1945 part.ParentGroup.DeleteAvatar(UUID);
1800 ParentPosition = part.GetWorldPosition(); 1946 ParentPosition = part.GetWorldPosition();
1801 ControllingClient.SendClearFollowCamProperties(part.ParentUUID); 1947 ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
1802 1948
@@ -1805,6 +1951,10 @@ namespace OpenSim.Region.Framework.Scenes
1805 1951
1806 ParentID = 0; 1952 ParentID = 0;
1807 ParentPart = null; 1953 ParentPart = null;
1954
1955 if (PhysicsActor == null)
1956 AddToPhysicalScene(false);
1957
1808 SendAvatarDataToAllAgents(); 1958 SendAvatarDataToAllAgents();
1809 m_requestedSitTargetID = 0; 1959 m_requestedSitTargetID = 0;
1810 1960
@@ -1812,6 +1962,9 @@ namespace OpenSim.Region.Framework.Scenes
1812 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); 1962 part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK);
1813 } 1963 }
1814 1964
1965 else if (PhysicsActor == null)
1966 AddToPhysicalScene(false);
1967
1815 Animator.TrySetMovementAnimation("STAND"); 1968 Animator.TrySetMovementAnimation("STAND");
1816 } 1969 }
1817 1970
@@ -1890,7 +2043,7 @@ namespace OpenSim.Region.Framework.Scenes
1890// m_log.DebugFormat("[SCENE PRESENCE]: {0} {1}", SitTargetisSet, SitTargetUnOccupied); 2043// m_log.DebugFormat("[SCENE PRESENCE]: {0} {1}", SitTargetisSet, SitTargetUnOccupied);
1891 2044
1892 if (PhysicsActor != null) 2045 if (PhysicsActor != null)
1893 m_sitAvatarHeight = PhysicsActor.Size.Z; 2046 m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f;
1894 2047
1895 bool canSit = false; 2048 bool canSit = false;
1896 pos = part.AbsolutePosition + offset; 2049 pos = part.AbsolutePosition + offset;
@@ -1935,7 +2088,7 @@ namespace OpenSim.Region.Framework.Scenes
1935 forceMouselook = part.GetForceMouselook(); 2088 forceMouselook = part.GetForceMouselook();
1936 2089
1937 ControllingClient.SendSitResponse( 2090 ControllingClient.SendSitResponse(
1938 targetID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); 2091 part.UUID, offset, sitOrientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook);
1939 2092
1940 m_requestedSitTargetUUID = targetID; 2093 m_requestedSitTargetUUID = targetID;
1941 2094
@@ -2217,14 +2370,36 @@ namespace OpenSim.Region.Framework.Scenes
2217 2370
2218 //Quaternion result = (sitTargetOrient * vq) * nq; 2371 //Quaternion result = (sitTargetOrient * vq) * nq;
2219 2372
2220 m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT; 2373 double x, y, z, m;
2374
2375 Quaternion r = sitTargetOrient;
2376 m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2377
2378 if (Math.Abs(1.0 - m) > 0.000001)
2379 {
2380 m = 1.0 / Math.Sqrt(m);
2381 r.X *= (float)m;
2382 r.Y *= (float)m;
2383 r.Z *= (float)m;
2384 r.W *= (float)m;
2385 }
2386
2387 x = 2 * (r.X * r.Z + r.Y * r.W);
2388 y = 2 * (-r.X * r.W + r.Y * r.Z);
2389 z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W;
2390
2391 Vector3 up = new Vector3((float)x, (float)y, (float)z);
2392 Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f;
2393 m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT;
2221 Rotation = sitTargetOrient; 2394 Rotation = sitTargetOrient;
2222 ParentPosition = part.AbsolutePosition; 2395 ParentPosition = part.AbsolutePosition;
2396 part.ParentGroup.AddAvatar(UUID);
2223 } 2397 }
2224 else 2398 else
2225 { 2399 {
2226 m_pos -= part.AbsolutePosition; 2400 m_pos -= part.AbsolutePosition;
2227 ParentPosition = part.AbsolutePosition; 2401 ParentPosition = part.AbsolutePosition;
2402 part.ParentGroup.AddAvatar(UUID);
2228 2403
2229// m_log.DebugFormat( 2404// m_log.DebugFormat(
2230// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", 2405// "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target",
@@ -2269,6 +2444,13 @@ namespace OpenSim.Region.Framework.Scenes
2269 Animator.RemoveAnimation(animID); 2444 Animator.RemoveAnimation(animID);
2270 } 2445 }
2271 2446
2447 public void avnHandleChangeAnim(UUID animID, bool addRemove,bool sendPack)
2448 {
2449 Animator.avnChangeAnim(animID, addRemove, sendPack);
2450 }
2451
2452
2453
2272 /// <summary> 2454 /// <summary>
2273 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector 2455 /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
2274 /// </summary> 2456 /// </summary>
@@ -2322,14 +2504,15 @@ namespace OpenSim.Region.Framework.Scenes
2322 direc.Z *= 2.6f; 2504 direc.Z *= 2.6f;
2323 2505
2324 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. 2506 // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
2325 Animator.TrySetMovementAnimation("PREJUMP"); 2507// Animator.TrySetMovementAnimation("PREJUMP");
2326 Animator.TrySetMovementAnimation("JUMP"); 2508// Animator.TrySetMovementAnimation("JUMP");
2327 } 2509 }
2328 } 2510 }
2329 } 2511 }
2330 2512
2331 // TODO: Add the force instead of only setting it to support multiple forces per frame? 2513 // TODO: Add the force instead of only setting it to support multiple forces per frame?
2332 m_forceToApply = direc; 2514 m_forceToApply = direc;
2515 Animator.UpdateMovementAnimations();
2333 } 2516 }
2334 2517
2335 #endregion 2518 #endregion
@@ -3064,6 +3247,9 @@ namespace OpenSim.Region.Framework.Scenes
3064 cAgent.AlwaysRun = SetAlwaysRun; 3247 cAgent.AlwaysRun = SetAlwaysRun;
3065 3248
3066 cAgent.Appearance = new AvatarAppearance(Appearance); 3249 cAgent.Appearance = new AvatarAppearance(Appearance);
3250
3251 cAgent.ParentPart = ParentUUID;
3252 cAgent.SitOffset = m_pos;
3067 3253
3068 lock (scriptedcontrols) 3254 lock (scriptedcontrols)
3069 { 3255 {
@@ -3072,7 +3258,7 @@ namespace OpenSim.Region.Framework.Scenes
3072 3258
3073 foreach (ScriptControllers c in scriptedcontrols.Values) 3259 foreach (ScriptControllers c in scriptedcontrols.Values)
3074 { 3260 {
3075 controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); 3261 controls[i++] = new ControllerData(c.objectID, c.itemID, (uint)c.ignoreControls, (uint)c.eventControls);
3076 } 3262 }
3077 cAgent.Controllers = controls; 3263 cAgent.Controllers = controls;
3078 } 3264 }
@@ -3083,6 +3269,7 @@ namespace OpenSim.Region.Framework.Scenes
3083 cAgent.Anims = Animator.Animations.ToArray(); 3269 cAgent.Anims = Animator.Animations.ToArray();
3084 } 3270 }
3085 catch { } 3271 catch { }
3272 cAgent.DefaultAnim = Animator.Animations.DefaultAnimation;
3086 3273
3087 // Attachment objects 3274 // Attachment objects
3088 List<SceneObjectGroup> attachments = GetAttachments(); 3275 List<SceneObjectGroup> attachments = GetAttachments();
@@ -3126,6 +3313,8 @@ namespace OpenSim.Region.Framework.Scenes
3126 CameraAtAxis = cAgent.AtAxis; 3313 CameraAtAxis = cAgent.AtAxis;
3127 CameraLeftAxis = cAgent.LeftAxis; 3314 CameraLeftAxis = cAgent.LeftAxis;
3128 CameraUpAxis = cAgent.UpAxis; 3315 CameraUpAxis = cAgent.UpAxis;
3316 ParentUUID = cAgent.ParentPart;
3317 m_prevSitOffset = cAgent.SitOffset;
3129 3318
3130 // When we get to the point of re-computing neighbors everytime this 3319 // When we get to the point of re-computing neighbors everytime this
3131 // changes, then start using the agent's drawdistance rather than the 3320 // changes, then start using the agent's drawdistance rather than the
@@ -3163,6 +3352,7 @@ namespace OpenSim.Region.Framework.Scenes
3163 foreach (ControllerData c in cAgent.Controllers) 3352 foreach (ControllerData c in cAgent.Controllers)
3164 { 3353 {
3165 ScriptControllers sc = new ScriptControllers(); 3354 ScriptControllers sc = new ScriptControllers();
3355 sc.objectID = c.ObjectID;
3166 sc.itemID = c.ItemID; 3356 sc.itemID = c.ItemID;
3167 sc.ignoreControls = (ScriptControlled)c.IgnoreControls; 3357 sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
3168 sc.eventControls = (ScriptControlled)c.EventControls; 3358 sc.eventControls = (ScriptControlled)c.EventControls;
@@ -3177,6 +3367,8 @@ namespace OpenSim.Region.Framework.Scenes
3177 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object? 3367 // FIXME: Why is this null check necessary? Where are the cases where we get a null Anims object?
3178 if (cAgent.Anims != null) 3368 if (cAgent.Anims != null)
3179 Animator.Animations.FromArray(cAgent.Anims); 3369 Animator.Animations.FromArray(cAgent.Anims);
3370 if (cAgent.DefaultAnim != null)
3371 Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero);
3180 3372
3181 if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0) 3373 if (cAgent.AttachmentObjects != null && cAgent.AttachmentObjects.Count > 0)
3182 { 3374 {
@@ -3249,7 +3441,7 @@ namespace OpenSim.Region.Framework.Scenes
3249 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; 3441 //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
3250 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; 3442 PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
3251 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong 3443 PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
3252 PhysicsActor.SubscribeEvents(500); 3444 PhysicsActor.SubscribeEvents(100);
3253 PhysicsActor.LocalID = LocalId; 3445 PhysicsActor.LocalID = LocalId;
3254 } 3446 }
3255 3447
@@ -3279,18 +3471,6 @@ namespace OpenSim.Region.Framework.Scenes
3279 if (IsChildAgent) 3471 if (IsChildAgent)
3280 return; 3472 return;
3281 3473
3282 //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
3283 // The Physics Scene will send updates every 500 ms grep: PhysicsActor.SubscribeEvents(
3284 // as of this comment the interval is set in AddToPhysicalScene
3285 if (Animator != null)
3286 {
3287// if (m_updateCount > 0)
3288// {
3289 Animator.UpdateMovementAnimations();
3290// m_updateCount--;
3291// }
3292 }
3293
3294 CollisionEventUpdate collisionData = (CollisionEventUpdate)e; 3474 CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
3295 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList; 3475 Dictionary<uint, ContactPoint> coldata = collisionData.m_objCollisionList;
3296 3476
@@ -3333,6 +3513,8 @@ namespace OpenSim.Region.Framework.Scenes
3333 } 3513 }
3334 } 3514 }
3335 3515
3516 RaiseCollisionScriptEvents(coldata);
3517
3336 // Gods do not take damage and Invulnerable is set depending on parcel/region flags 3518 // Gods do not take damage and Invulnerable is set depending on parcel/region flags
3337 if (Invulnerable || GodLevel > 0) 3519 if (Invulnerable || GodLevel > 0)
3338 return; 3520 return;
@@ -3665,10 +3847,15 @@ namespace OpenSim.Region.Framework.Scenes
3665 3847
3666 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) 3848 public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
3667 { 3849 {
3850 SceneObjectPart p = m_scene.GetSceneObjectPart(Obj_localID);
3851 if (p == null)
3852 return;
3853
3668 ScriptControllers obj = new ScriptControllers(); 3854 ScriptControllers obj = new ScriptControllers();
3669 obj.ignoreControls = ScriptControlled.CONTROL_ZERO; 3855 obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
3670 obj.eventControls = ScriptControlled.CONTROL_ZERO; 3856 obj.eventControls = ScriptControlled.CONTROL_ZERO;
3671 3857
3858 obj.objectID = p.ParentGroup.UUID;
3672 obj.itemID = Script_item_UUID; 3859 obj.itemID = Script_item_UUID;
3673 if (pass_on == 0 && accept == 0) 3860 if (pass_on == 0 && accept == 0)
3674 { 3861 {
@@ -3717,6 +3904,21 @@ namespace OpenSim.Region.Framework.Scenes
3717 ControllingClient.SendTakeControls(int.MaxValue, false, false); 3904 ControllingClient.SendTakeControls(int.MaxValue, false, false);
3718 } 3905 }
3719 3906
3907 private void UnRegisterSeatControls(UUID obj)
3908 {
3909 List<UUID> takers = new List<UUID>();
3910
3911 foreach (ScriptControllers c in scriptedcontrols.Values)
3912 {
3913 if (c.objectID == obj)
3914 takers.Add(c.itemID);
3915 }
3916 foreach (UUID t in takers)
3917 {
3918 UnRegisterControlEventsToScript(0, t);
3919 }
3920 }
3921
3720 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) 3922 public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
3721 { 3923 {
3722 ScriptControllers takecontrols; 3924 ScriptControllers takecontrols;
@@ -4035,6 +4237,12 @@ namespace OpenSim.Region.Framework.Scenes
4035 4237
4036 private void CheckAndAdjustLandingPoint(ref Vector3 pos) 4238 private void CheckAndAdjustLandingPoint(ref Vector3 pos)
4037 { 4239 {
4240 string reason;
4241
4242 // Honor bans
4243 if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y))
4244 return;
4245
4038 SceneObjectGroup telehub = null; 4246 SceneObjectGroup telehub = null;
4039 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) 4247 if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null)
4040 { 4248 {
@@ -4074,11 +4282,206 @@ namespace OpenSim.Region.Framework.Scenes
4074 pos = land.LandData.UserLocation; 4282 pos = land.LandData.UserLocation;
4075 } 4283 }
4076 } 4284 }
4077 4285
4078 land.SendLandUpdateToClient(ControllingClient); 4286 land.SendLandUpdateToClient(ControllingClient);
4079 } 4287 }
4080 } 4288 }
4081 4289
4290 private DetectedObject CreateDetObject(SceneObjectPart obj)
4291 {
4292 DetectedObject detobj = new DetectedObject();
4293 detobj.keyUUID = obj.UUID;
4294 detobj.nameStr = obj.Name;
4295 detobj.ownerUUID = obj.OwnerID;
4296 detobj.posVector = obj.AbsolutePosition;
4297 detobj.rotQuat = obj.GetWorldRotation();
4298 detobj.velVector = obj.Velocity;
4299 detobj.colliderType = 0;
4300 detobj.groupUUID = obj.GroupID;
4301
4302 return detobj;
4303 }
4304
4305 private DetectedObject CreateDetObject(ScenePresence av)
4306 {
4307 DetectedObject detobj = new DetectedObject();
4308 detobj.keyUUID = av.UUID;
4309 detobj.nameStr = av.ControllingClient.Name;
4310 detobj.ownerUUID = av.UUID;
4311 detobj.posVector = av.AbsolutePosition;
4312 detobj.rotQuat = av.Rotation;
4313 detobj.velVector = av.Velocity;
4314 detobj.colliderType = 0;
4315 detobj.groupUUID = av.ControllingClient.ActiveGroupId;
4316
4317 return detobj;
4318 }
4319
4320 private DetectedObject CreateDetObjectForGround()
4321 {
4322 DetectedObject detobj = new DetectedObject();
4323 detobj.keyUUID = UUID.Zero;
4324 detobj.nameStr = "";
4325 detobj.ownerUUID = UUID.Zero;
4326 detobj.posVector = AbsolutePosition;
4327 detobj.rotQuat = Quaternion.Identity;
4328 detobj.velVector = Vector3.Zero;
4329 detobj.colliderType = 0;
4330 detobj.groupUUID = UUID.Zero;
4331
4332 return detobj;
4333 }
4334
4335 private ColliderArgs CreateColliderArgs(SceneObjectPart dest, List<uint> colliders)
4336 {
4337 ColliderArgs colliderArgs = new ColliderArgs();
4338 List<DetectedObject> colliding = new List<DetectedObject>();
4339 foreach (uint localId in colliders)
4340 {
4341 if (localId == 0)
4342 continue;
4343
4344 SceneObjectPart obj = m_scene.GetSceneObjectPart(localId);
4345 if (obj != null)
4346 {
4347 if (!dest.CollisionFilteredOut(obj.UUID, obj.Name))
4348 colliding.Add(CreateDetObject(obj));
4349 }
4350 else
4351 {
4352 ScenePresence av = m_scene.GetScenePresence(localId);
4353 if (av != null && (!av.IsChildAgent))
4354 {
4355 if (!dest.CollisionFilteredOut(av.UUID, av.Name))
4356 colliding.Add(CreateDetObject(av));
4357 }
4358 }
4359 }
4360
4361 colliderArgs.Colliders = colliding;
4362
4363 return colliderArgs;
4364 }
4365
4366 private delegate void ScriptCollidingNotification(uint localID, ColliderArgs message);
4367
4368 private void SendCollisionEvent(SceneObjectGroup dest, scriptEvents ev, List<uint> colliders, ScriptCollidingNotification notify)
4369 {
4370 ColliderArgs CollidingMessage;
4371
4372 if (colliders.Count > 0)
4373 {
4374 if ((dest.RootPart.ScriptEvents & ev) != 0)
4375 {
4376 CollidingMessage = CreateColliderArgs(dest.RootPart, colliders);
4377
4378 if (CollidingMessage.Colliders.Count > 0)
4379 notify(dest.RootPart.LocalId, CollidingMessage);
4380 }
4381 }
4382 }
4383
4384 private void SendLandCollisionEvent(SceneObjectGroup dest, scriptEvents ev, ScriptCollidingNotification notify)
4385 {
4386 if ((dest.RootPart.ScriptEvents & ev) != 0)
4387 {
4388 ColliderArgs LandCollidingMessage = new ColliderArgs();
4389 List<DetectedObject> colliding = new List<DetectedObject>();
4390
4391 colliding.Add(CreateDetObjectForGround());
4392 LandCollidingMessage.Colliders = colliding;
4393
4394 notify(dest.RootPart.LocalId, LandCollidingMessage);
4395 }
4396 }
4397
4398 private void RaiseCollisionScriptEvents(Dictionary<uint, ContactPoint> coldata)
4399 {
4400 try
4401 {
4402 List<uint> thisHitColliders = new List<uint>();
4403 List<uint> endedColliders = new List<uint>();
4404 List<uint> startedColliders = new List<uint>();
4405 List<CollisionForSoundInfo> soundinfolist = new List<CollisionForSoundInfo>();
4406 CollisionForSoundInfo soundinfo;
4407 ContactPoint curcontact;
4408
4409 if (coldata.Count == 0)
4410 {
4411 if (m_lastColliders.Count == 0)
4412 return; // nothing to do
4413
4414 foreach (uint localID in m_lastColliders)
4415 {
4416 endedColliders.Add(localID);
4417 }
4418 m_lastColliders.Clear();
4419 }
4420
4421 else
4422 {
4423 foreach (uint id in coldata.Keys)
4424 {
4425 thisHitColliders.Add(id);
4426 if (!m_lastColliders.Contains(id))
4427 {
4428 startedColliders.Add(id);
4429 curcontact = coldata[id];
4430 if (Math.Abs(curcontact.RelativeSpeed) > 0.2)
4431 {
4432 soundinfo = new CollisionForSoundInfo();
4433 soundinfo.colliderID = id;
4434 soundinfo.position = curcontact.Position;
4435 soundinfo.relativeVel = curcontact.RelativeSpeed;
4436 soundinfolist.Add(soundinfo);
4437 }
4438 }
4439 //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
4440 }
4441
4442 // calculate things that ended colliding
4443 foreach (uint localID in m_lastColliders)
4444 {
4445 if (!thisHitColliders.Contains(localID))
4446 {
4447 endedColliders.Add(localID);
4448 }
4449 }
4450 //add the items that started colliding this time to the last colliders list.
4451 foreach (uint localID in startedColliders)
4452 {
4453 m_lastColliders.Add(localID);
4454 }
4455 // remove things that ended colliding from the last colliders list
4456 foreach (uint localID in endedColliders)
4457 {
4458 m_lastColliders.Remove(localID);
4459 }
4460
4461 if (soundinfolist.Count > 0)
4462 CollisionSounds.AvatarCollisionSound(this, soundinfolist);
4463 }
4464
4465 foreach (SceneObjectGroup att in GetAttachments())
4466 {
4467 SendCollisionEvent(att, scriptEvents.collision_start, startedColliders, m_scene.EventManager.TriggerScriptCollidingStart);
4468 SendCollisionEvent(att, scriptEvents.collision , m_lastColliders , m_scene.EventManager.TriggerScriptColliding);
4469 SendCollisionEvent(att, scriptEvents.collision_end , endedColliders , m_scene.EventManager.TriggerScriptCollidingEnd);
4470
4471 if (startedColliders.Contains(0))
4472 SendLandCollisionEvent(att, scriptEvents.land_collision_start, m_scene.EventManager.TriggerScriptLandCollidingStart);
4473 if (m_lastColliders.Contains(0))
4474 SendLandCollisionEvent(att, scriptEvents.land_collision, m_scene.EventManager.TriggerScriptLandColliding);
4475 if (endedColliders.Contains(0))
4476 SendLandCollisionEvent(att, scriptEvents.land_collision_end, m_scene.EventManager.TriggerScriptLandCollidingEnd);
4477 }
4478 }
4479 finally
4480 {
4481 m_collisionEventFlag = false;
4482 }
4483 }
4484
4082 private void TeleportFlagsDebug() { 4485 private void TeleportFlagsDebug() {
4083 4486
4084 // Some temporary debugging help to show all the TeleportFlags we have... 4487 // Some temporary debugging help to show all the TeleportFlags we have...
@@ -4103,6 +4506,5 @@ namespace OpenSim.Region.Framework.Scenes
4103 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); 4506 m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************");
4104 4507
4105 } 4508 }
4106
4107 } 4509 }
4108} 4510}
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 0b34156..e223f47 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);
@@ -348,6 +354,21 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
348 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2); 354 m_SOPXmlProcessors.Add("PayPrice2", ProcessPayPrice2);
349 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3); 355 m_SOPXmlProcessors.Add("PayPrice3", ProcessPayPrice3);
350 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4); 356 m_SOPXmlProcessors.Add("PayPrice4", ProcessPayPrice4);
357
358 m_SOPXmlProcessors.Add("Buoyancy", ProcessBuoyancy);
359 m_SOPXmlProcessors.Add("Force", ProcessForce);
360 m_SOPXmlProcessors.Add("Torque", ProcessTorque);
361 m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive);
362
363
364 m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle);
365
366 m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType);
367 m_SOPXmlProcessors.Add("Density", ProcessDensity);
368 m_SOPXmlProcessors.Add("Friction", ProcessFriction);
369 m_SOPXmlProcessors.Add("Bounce", ProcessBounce);
370 m_SOPXmlProcessors.Add("GravityModifier", ProcessGravityModifier);
371
351 #endregion 372 #endregion
352 373
353 #region TaskInventoryXmlProcessors initialization 374 #region TaskInventoryXmlProcessors initialization
@@ -375,7 +396,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
375 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask); 396 m_TaskInventoryXmlProcessors.Add("PermsMask", ProcessTIPermsMask);
376 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType); 397 m_TaskInventoryXmlProcessors.Add("Type", ProcessTIType);
377 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged); 398 m_TaskInventoryXmlProcessors.Add("OwnerChanged", ProcessTIOwnerChanged);
378 399
379 #endregion 400 #endregion
380 401
381 #region ShapeXmlProcessors initialization 402 #region ShapeXmlProcessors initialization
@@ -575,6 +596,49 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
575 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty); 596 obj.ClickAction = (byte)reader.ReadElementContentAsInt("ClickAction", String.Empty);
576 } 597 }
577 598
599 private static void ProcessPhysicsShapeType(SceneObjectPart obj, XmlTextReader reader)
600 {
601 obj.PhysicsShapeType = (byte)reader.ReadElementContentAsInt("PhysicsShapeType", String.Empty);
602 }
603
604 private static void ProcessDensity(SceneObjectPart obj, XmlTextReader reader)
605 {
606 obj.Density = reader.ReadElementContentAsFloat("Density", String.Empty);
607 }
608
609 private static void ProcessFriction(SceneObjectPart obj, XmlTextReader reader)
610 {
611 obj.Friction = reader.ReadElementContentAsFloat("Friction", String.Empty);
612 }
613
614 private static void ProcessBounce(SceneObjectPart obj, XmlTextReader reader)
615 {
616 obj.Bounciness = reader.ReadElementContentAsFloat("Bounce", String.Empty);
617 }
618
619 private static void ProcessGravityModifier(SceneObjectPart obj, XmlTextReader reader)
620 {
621 obj.GravityModifier = reader.ReadElementContentAsFloat("GravityModifier", String.Empty);
622 }
623
624 private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader)
625 {
626 bool errors = false;
627 SOPVehicle _vehicle = new SOPVehicle();
628
629 _vehicle.FromXml2(reader, out errors);
630
631 if (errors)
632 {
633 obj.sopVehicle = null;
634 m_log.DebugFormat(
635 "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.",
636 obj.Name, obj.UUID);
637 }
638 else
639 obj.sopVehicle = _vehicle;
640 }
641
578 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) 642 private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader)
579 { 643 {
580 List<string> errorNodeNames; 644 List<string> errorNodeNames;
@@ -739,6 +803,25 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
739 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty); 803 obj.PayPrice[4] = (int)reader.ReadElementContentAsInt("PayPrice4", String.Empty);
740 } 804 }
741 805
806 private static void ProcessBuoyancy(SceneObjectPart obj, XmlTextReader reader)
807 {
808 obj.Buoyancy = (float)reader.ReadElementContentAsFloat("Buoyancy", String.Empty);
809 }
810
811 private static void ProcessForce(SceneObjectPart obj, XmlTextReader reader)
812 {
813 obj.Force = Util.ReadVector(reader, "Force");
814 }
815 private static void ProcessTorque(SceneObjectPart obj, XmlTextReader reader)
816 {
817 obj.Torque = Util.ReadVector(reader, "Torque");
818 }
819
820 private static void ProcessVolumeDetectActive(SceneObjectPart obj, XmlTextReader reader)
821 {
822 obj.VolumeDetectActive = Util.ReadBoolean(reader);
823 }
824
742 #endregion 825 #endregion
743 826
744 #region TaskInventoryXmlProcessors 827 #region TaskInventoryXmlProcessors
@@ -1126,6 +1209,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1126 }); 1209 });
1127 1210
1128 writer.WriteEndElement(); 1211 writer.WriteEndElement();
1212
1213 if (sog.RootPart.KeyframeMotion != null)
1214 {
1215 Byte[] data = sog.RootPart.KeyframeMotion.Serialize();
1216
1217 writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty);
1218 writer.WriteBase64(data, 0, data.Length);
1219 writer.WriteEndElement();
1220 }
1221
1129 writer.WriteEndElement(); 1222 writer.WriteEndElement();
1130 } 1223 }
1131 1224
@@ -1225,6 +1318,27 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1225 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); 1318 writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString());
1226 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); 1319 writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString());
1227 1320
1321 writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString());
1322
1323 WriteVector(writer, "Force", sop.Force);
1324 WriteVector(writer, "Torque", sop.Torque);
1325
1326 writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower());
1327
1328 if (sop.sopVehicle != null)
1329 sop.sopVehicle.ToXml2(writer);
1330
1331 if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType())
1332 writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower());
1333 if (sop.Density != 1000.0f)
1334 writer.WriteElementString("Density", sop.Density.ToString().ToLower());
1335 if (sop.Friction != 0.6f)
1336 writer.WriteElementString("Friction", sop.Friction.ToString().ToLower());
1337 if (sop.Bounciness != 0.5f)
1338 writer.WriteElementString("Bounce", sop.Bounciness.ToString().ToLower());
1339 if (sop.GravityModifier != 1.0f)
1340 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
1341
1228 writer.WriteEndElement(); 1342 writer.WriteEndElement();
1229 } 1343 }
1230 1344
@@ -1449,12 +1563,6 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1449 { 1563 {
1450 TaskInventoryDictionary tinv = new TaskInventoryDictionary(); 1564 TaskInventoryDictionary tinv = new TaskInventoryDictionary();
1451 1565
1452 if (reader.IsEmptyElement)
1453 {
1454 reader.Read();
1455 return tinv;
1456 }
1457
1458 reader.ReadStartElement(name, String.Empty); 1566 reader.ReadStartElement(name, String.Empty);
1459 1567
1460 while (reader.Name == "TaskInventoryItem") 1568 while (reader.Name == "TaskInventoryItem")
diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
index 87af311..0efe4c4 100644
--- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
+++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs
@@ -83,7 +83,20 @@ namespace OpenSim.Region.Framework.Scenes
83 OutPacketsPerSecond = 18, 83 OutPacketsPerSecond = 18,
84 PendingDownloads = 19, 84 PendingDownloads = 19,
85 PendingUploads = 20, 85 PendingUploads = 20,
86 VirtualSizeKB = 21,
87 ResidentSizeKB = 22,
88 PendingLocalUploads = 23,
86 UnAckedBytes = 24, 89 UnAckedBytes = 24,
90 PhysicsPinnedTasks = 25,
91 PhysicsLODTasks = 26,
92 PhysicsStepMS = 27,
93 PhysicsShapeMS = 28,
94 PhysicsOtherMS = 29,
95 PhysicsMemory = 30,
96 ScriptEPS = 31,
97 SimSpareTime = 32,
98 SimSleepTime = 33,
99 IOPumpTime = 34
87 } 100 }
88 101
89 /// <summary> 102 /// <summary>
@@ -139,7 +152,7 @@ namespace OpenSim.Region.Framework.Scenes
139 152
140 // saved last reported value so there is something available for llGetRegionFPS 153 // saved last reported value so there is something available for llGetRegionFPS
141 private float lastReportedSimFPS = 0; 154 private float lastReportedSimFPS = 0;
142 private float[] lastReportedSimStats = new float[21]; 155 private float[] lastReportedSimStats = new float[23];
143 private float m_pfps = 0; 156 private float m_pfps = 0;
144 157
145 /// <summary> 158 /// <summary>
@@ -158,6 +171,8 @@ namespace OpenSim.Region.Framework.Scenes
158 private int m_physicsMS = 0; 171 private int m_physicsMS = 0;
159 private int m_imageMS = 0; 172 private int m_imageMS = 0;
160 private int m_otherMS = 0; 173 private int m_otherMS = 0;
174 private int m_sleeptimeMS = 0;
175
161 176
162//Ckrinke: (3-21-08) Comment out to remove a compiler warning. Bring back into play when needed. 177//Ckrinke: (3-21-08) Comment out to remove a compiler warning. Bring back into play when needed.
163//Ckrinke private int m_scriptMS = 0; 178//Ckrinke private int m_scriptMS = 0;
@@ -220,7 +235,7 @@ namespace OpenSim.Region.Framework.Scenes
220 235
221 private void statsHeartBeat(object sender, EventArgs e) 236 private void statsHeartBeat(object sender, EventArgs e)
222 { 237 {
223 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[21]; 238 SimStatsPacket.StatBlock[] sb = new SimStatsPacket.StatBlock[23];
224 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock(); 239 SimStatsPacket.RegionBlock rb = new SimStatsPacket.RegionBlock();
225 240
226 // Know what's not thread safe in Mono... modifying timers. 241 // Know what's not thread safe in Mono... modifying timers.
@@ -258,6 +273,33 @@ namespace OpenSim.Region.Framework.Scenes
258 physfps = 0; 273 physfps = 0;
259 274
260#endregion 275#endregion
276 float factor = 1 / statsUpdateFactor;
277 if (reportedFPS <= 0)
278 reportedFPS = 1;
279
280 float perframe = 1.0f / (float)reportedFPS;
281
282 float TotalFrameTime = m_frameMS * perframe;
283
284 float targetframetime = 1100.0f / (float)m_nominalReportedFps;
285
286 float sparetime;
287 float sleeptime;
288 if (TotalFrameTime > targetframetime)
289 {
290 sparetime = 0;
291 sleeptime = 0;
292 }
293 else
294 {
295 sparetime = m_frameMS - m_physicsMS - m_agentMS;
296 sparetime *= perframe;
297 if (sparetime < 0)
298 sparetime = 0;
299 else if (sparetime > TotalFrameTime)
300 sparetime = TotalFrameTime;
301 sleeptime = m_sleeptimeMS * perframe;
302 }
261 303
262 m_rootAgents = m_scene.SceneGraph.GetRootAgentCount(); 304 m_rootAgents = m_scene.SceneGraph.GetRootAgentCount();
263 m_childAgents = m_scene.SceneGraph.GetChildAgentCount(); 305 m_childAgents = m_scene.SceneGraph.GetChildAgentCount();
@@ -269,17 +311,15 @@ namespace OpenSim.Region.Framework.Scenes
269 // so that stat numbers are always consistent. 311 // so that stat numbers are always consistent.
270 CheckStatSanity(); 312 CheckStatSanity();
271 313
272 //Our time dilation is 0.91 when we're running a full speed, 314 // other MS is actually simulation time
273 // therefore to make sure we get an appropriate range, 315 // m_otherMS = m_frameMS - m_physicsMS - m_imageMS - m_netMS - m_agentMS;
274 // we have to factor in our error. (0.10f * statsUpdateFactor) 316 // m_imageMS m_netMS are not included in m_frameMS
275 // multiplies the fix for the error times the amount of times it'll occur a second
276 // / 10 divides the value by the number of times the sim heartbeat runs (10fps)
277 // Then we divide the whole amount by the amount of seconds pass in between stats updates.
278 317
279 // 'statsUpdateFactor' is how often stats packets are sent in seconds. Used below to change 318 m_otherMS = m_frameMS - m_physicsMS - m_agentMS - m_sleeptimeMS;
280 // values to X-per-second values. 319 if (m_otherMS < 0)
320 m_otherMS = 0;
281 321
282 for (int i = 0; i < 21; i++) 322 for (int i = 0; i < 23; i++)
283 { 323 {
284 sb[i] = new SimStatsPacket.StatBlock(); 324 sb[i] = new SimStatsPacket.StatBlock();
285 } 325 }
@@ -309,19 +349,25 @@ namespace OpenSim.Region.Framework.Scenes
309 sb[7].StatValue = m_activePrim; 349 sb[7].StatValue = m_activePrim;
310 350
311 sb[8].StatID = (uint)Stats.FrameMS; 351 sb[8].StatID = (uint)Stats.FrameMS;
312 sb[8].StatValue = m_frameMS / statsUpdateFactor; 352 // sb[8].StatValue = m_frameMS / statsUpdateFactor;
353 sb[8].StatValue = TotalFrameTime;
313 354
314 sb[9].StatID = (uint)Stats.NetMS; 355 sb[9].StatID = (uint)Stats.NetMS;
315 sb[9].StatValue = m_netMS / statsUpdateFactor; 356 // sb[9].StatValue = m_netMS / statsUpdateFactor;
357 sb[9].StatValue = m_netMS * perframe;
316 358
317 sb[10].StatID = (uint)Stats.PhysicsMS; 359 sb[10].StatID = (uint)Stats.PhysicsMS;
318 sb[10].StatValue = m_physicsMS / statsUpdateFactor; 360 // sb[10].StatValue = m_physicsMS / statsUpdateFactor;
361 sb[10].StatValue = m_physicsMS * perframe;
319 362
320 sb[11].StatID = (uint)Stats.ImageMS ; 363 sb[11].StatID = (uint)Stats.ImageMS ;
321 sb[11].StatValue = m_imageMS / statsUpdateFactor; 364 // sb[11].StatValue = m_imageMS / statsUpdateFactor;
365 sb[11].StatValue = m_imageMS * perframe;
322 366
323 sb[12].StatID = (uint)Stats.OtherMS; 367 sb[12].StatID = (uint)Stats.OtherMS;
324 sb[12].StatValue = m_otherMS / statsUpdateFactor; 368 // sb[12].StatValue = m_otherMS / statsUpdateFactor;
369 sb[12].StatValue = m_otherMS * perframe;
370
325 371
326 sb[13].StatID = (uint)Stats.InPacketsPerSecond; 372 sb[13].StatID = (uint)Stats.InPacketsPerSecond;
327 sb[13].StatValue = (m_inPacketsPerSecond / statsUpdateFactor); 373 sb[13].StatValue = (m_inPacketsPerSecond / statsUpdateFactor);
@@ -333,7 +379,8 @@ namespace OpenSim.Region.Framework.Scenes
333 sb[15].StatValue = m_unAckedBytes; 379 sb[15].StatValue = m_unAckedBytes;
334 380
335 sb[16].StatID = (uint)Stats.AgentMS; 381 sb[16].StatID = (uint)Stats.AgentMS;
336 sb[16].StatValue = m_agentMS / statsUpdateFactor; 382// sb[16].StatValue = m_agentMS / statsUpdateFactor;
383 sb[16].StatValue = m_agentMS * perframe;
337 384
338 sb[17].StatID = (uint)Stats.PendingDownloads; 385 sb[17].StatID = (uint)Stats.PendingDownloads;
339 sb[17].StatValue = m_pendingDownloads; 386 sb[17].StatValue = m_pendingDownloads;
@@ -346,8 +393,14 @@ namespace OpenSim.Region.Framework.Scenes
346 393
347 sb[20].StatID = (uint)Stats.ScriptLinesPerSecond; 394 sb[20].StatID = (uint)Stats.ScriptLinesPerSecond;
348 sb[20].StatValue = m_scriptLinesPerSecond / statsUpdateFactor; 395 sb[20].StatValue = m_scriptLinesPerSecond / statsUpdateFactor;
349 396
350 for (int i = 0; i < 21; i++) 397 sb[21].StatID = (uint)Stats.SimSpareTime;
398 sb[21].StatValue = sparetime;
399
400 sb[22].StatID = (uint)Stats.SimSleepTime;
401 sb[22].StatValue = sleeptime;
402
403 for (int i = 0; i < 23; i++)
351 { 404 {
352 lastReportedSimStats[i] = sb[i].StatValue; 405 lastReportedSimStats[i] = sb[i].StatValue;
353 } 406 }
@@ -401,6 +454,7 @@ namespace OpenSim.Region.Framework.Scenes
401 m_physicsMS = 0; 454 m_physicsMS = 0;
402 m_imageMS = 0; 455 m_imageMS = 0;
403 m_otherMS = 0; 456 m_otherMS = 0;
457 m_sleeptimeMS = 0;
404 458
405//Ckrinke This variable is not used, so comment to remove compiler warning until it is used. 459//Ckrinke This variable is not used, so comment to remove compiler warning until it is used.
406//Ckrinke m_scriptMS = 0; 460//Ckrinke m_scriptMS = 0;
@@ -504,6 +558,11 @@ namespace OpenSim.Region.Framework.Scenes
504 m_otherMS += ms; 558 m_otherMS += ms;
505 } 559 }
506 560
561 public void addSleepMS(int ms)
562 {
563 m_sleeptimeMS += ms;
564 }
565
507 public void AddPendingDownloads(int count) 566 public void AddPendingDownloads(int count)
508 { 567 {
509 m_pendingDownloads += count; 568 m_pendingDownloads += count;
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;