aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorJustin Clarke Casey2008-10-09 22:41:07 +0000
committerJustin Clarke Casey2008-10-09 22:41:07 +0000
commit4e3bc9a63ebf9eb292eccca7b104b6914fe7de5a (patch)
treebd950d0052c787a59b9309567f260b3858adcf52 /OpenSim
parent- Fix the build for monodevelop, too. If that breaks the build on Windows, (diff)
downloadopensim-SC-4e3bc9a63ebf9eb292eccca7b104b6914fe7de5a.zip
opensim-SC-4e3bc9a63ebf9eb292eccca7b104b6914fe7de5a.tar.gz
opensim-SC-4e3bc9a63ebf9eb292eccca7b104b6914fe7de5a.tar.bz2
opensim-SC-4e3bc9a63ebf9eb292eccca7b104b6914fe7de5a.tar.xz
* Apply http://opensimulator.org/mantis/view.php?id=2373
* Many llSensor() improvements, though sensoring isn't perfect yet * thanks idb!
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs315
1 files changed, 242 insertions, 73 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index c4240d8..68c7392 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -45,10 +45,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
45 m_CmdManager = CmdManager; 45 m_CmdManager = CmdManager;
46 } 46 }
47 47
48 public Dictionary<uint, Dictionary<UUID, LSL_Types.list>> SenseEvents =
49 new Dictionary<uint, Dictionary<UUID, LSL_Types.list>>();
50 private Object SenseLock = new Object(); 48 private Object SenseLock = new Object();
51 49
50 private const int AGENT = 1;
51 private const int ACTIVE = 2;
52 private const int PASSIVE = 4;
53 private const int SCRIPTED = 8;
54
55 private double maximumRange = 96.0;
56 private int maximumToReturn = 16;
57
52 // 58 //
53 // SenseRepeater and Sensors 59 // SenseRepeater and Sensors
54 // 60 //
@@ -87,7 +93,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
87 ts.name = name; 93 ts.name = name;
88 ts.keyID = keyID; 94 ts.keyID = keyID;
89 ts.type = type; 95 ts.type = type;
90 ts.range = range; 96 if (range > maximumRange)
97 ts.range = maximumRange;
98 else
99 ts.range = range;
91 ts.arc = arc; 100 ts.arc = arc;
92 ts.host = host; 101 ts.host = host;
93 102
@@ -150,7 +159,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
150 ts.name = name; 159 ts.name = name;
151 ts.keyID = keyID; 160 ts.keyID = keyID;
152 ts.type = type; 161 ts.type = type;
153 ts.range = range; 162 if (range > maximumRange)
163 ts.range = maximumRange;
164 else
165 ts.range = range;
154 ts.arc = arc; 166 ts.arc = arc;
155 ts.host = host; 167 ts.host = host;
156 SensorSweep(ts); 168 SensorSweep(ts);
@@ -158,13 +170,101 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
158 170
159 private void SensorSweep(SenseRepeatClass ts) 171 private void SensorSweep(SenseRepeatClass ts)
160 { 172 {
161 SceneObjectPart SensePoint = ts.host; 173 if (ts.host == null)
162
163 if (SensePoint == null)
164 { 174 {
165 return; 175 return;
166 } 176 }
167 177
178 LSL_Types.list SensedObjects = new LSL_Types.list();
179
180 // Is the sensor type is AGENT and not SCRIPTED then include agents
181 if ((ts.type & AGENT) != 0 && (ts.type & SCRIPTED) == 0)
182 {
183 doAgentSensor(ts, SensedObjects);
184 }
185
186 // If SCRIPTED or PASSIVE or ACTIVE check objects
187 if ((ts.type & SCRIPTED) != 0 || (ts.type & PASSIVE) != 0 || (ts.type & ACTIVE) != 0)
188 {
189 doObjectSensor(ts, SensedObjects);
190 }
191
192 lock (SenseLock)
193 {
194 if (SensedObjects.Length == 0)
195 {
196 // send a "no_sensor"
197 // Add it to queue
198 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
199 new EventParams("no_sensor", new Object[0],
200 new DetectParams[0]));
201 }
202 else
203 {
204 // the sort is stride = 2 and ascending to get everything ordered by distance
205 SensedObjects = SensedObjects.Sort(2, 1);
206 int count = SensedObjects.Length;
207 int idx;
208 List<DetectParams> detected = new List<DetectParams>();
209 for (idx = 0; idx < count; idx++)
210 {
211 try
212 {
213 DetectParams detect = new DetectParams();
214 detect.Key = (UUID)(SensedObjects.Data[(idx * 2) + 1]);
215 detect.Populate(m_CmdManager.m_ScriptEngine.World);
216 detected.Add(detect);
217 }
218 catch (Exception)
219 {
220 // Ignore errors, the object has been deleted or the avatar has gone and
221 // there was a problem in detect.Populate so nothing added to the list
222 }
223 if (detected.Count == maximumToReturn)
224 break;
225 }
226
227 if (detected.Count == 0)
228 {
229 // To get here with zero in the list there must have been some sort of problem
230 // like the object being deleted or the avatar leaving to have caused some
231 // difficulty during the Populate above so fire a no_sensor event
232 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
233 new EventParams("no_sensor", new Object[0],
234 new DetectParams[0]));
235 }
236 else
237 {
238 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
239 new EventParams("sensor",
240 new Object[] {new LSL_Types.LSLInteger(detected.Count) },
241 detected.ToArray()));
242 }
243 }
244 }
245 }
246
247 private void doObjectSensor(SenseRepeatClass ts, LSL_Types.list SensedObjects)
248 {
249 List<EntityBase> Entities;
250
251 // If this is an object sense by key try to get it directly
252 // rather than getting a list to scan through
253 if (ts.keyID != UUID.Zero)
254 {
255 EntityBase e = null;
256 m_CmdManager.m_ScriptEngine.World.Entities.TryGetValue(ts.keyID, out e);
257 if (e == null)
258 return;
259 Entities = new List<EntityBase>();
260 Entities.Add(e);
261 }
262 else
263 {
264 Entities = m_CmdManager.m_ScriptEngine.World.GetEntities();
265 }
266 SceneObjectPart SensePoint = ts.host;
267
168 Vector3 sensorPos = SensePoint.AbsolutePosition; 268 Vector3 sensorPos = SensePoint.AbsolutePosition;
169 Vector3 regionPos = new Vector3(m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocX * Constants.RegionSize, m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocY * Constants.RegionSize, 0); 269 Vector3 regionPos = new Vector3(m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocX * Constants.RegionSize, m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
170 Vector3 fromRegionPos = sensorPos + regionPos; 270 Vector3 fromRegionPos = sensorPos + regionPos;
@@ -174,37 +274,55 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
174 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); 274 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
175 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); 275 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
176 276
177 // Here we should do some smart culling ... 277 Vector3 ZeroVector = new Vector3(0, 0, 0);
178 // math seems quicker than strings so try that first 278
179 LSL_Types.list SensedObjects = new LSL_Types.list(); 279 bool nameSearch = (ts.name != null && ts.name != "");
180 LSL_Types.Vector3 ZeroVector = new LSL_Types.Vector3(0, 0, 0); 280 SceneObjectGroup group;
181 281
182 foreach (EntityBase ent in m_CmdManager.m_ScriptEngine.World.Entities.Values) 282 foreach (EntityBase ent in Entities)
183 { 283 {
284 bool keep = true;
285
286 if (nameSearch && ent.Name != ts.name) // Wrong name and it is a named search
287 continue;
288
289 if (ent.IsDeleted) // taken so long to do this it has gone from the scene
290 continue;
291
292 if (!(ent is SceneObjectGroup)) // dont bother if it is a pesky avatar
293 continue;
294
184 Vector3 toRegionPos = ent.AbsolutePosition + regionPos; 295 Vector3 toRegionPos = ent.AbsolutePosition + regionPos;
185 double dis = Math.Abs((double)Util.GetDistanceTo(toRegionPos, fromRegionPos)); 296 double dis = Math.Abs((double)Util.GetDistanceTo(toRegionPos, fromRegionPos));
186 if (dis <= ts.range) 297 if (keep && dis <= ts.range && ts.host.UUID != ent.UUID)
187 { 298 {
188 // In Range, is it the right Type ? 299 // In Range and not the object containing the script, is it the right Type ?
189 int objtype = 0; 300 int objtype = 0;
190 301
191 if (m_CmdManager.m_ScriptEngine.World.GetScenePresence(ent.UUID) != null) objtype |= 0x01; // actor 302 SceneObjectPart part = ((SceneObjectGroup)ent).RootPart;
192 if (ent.Velocity.Equals(ZeroVector)) 303 if (part.AttachmentPoint != 0) // Attached so ignore
193 objtype |= 0x04; // passive non-moving 304 continue;
194 else
195 objtype |= 0x02; // active moving
196
197 SceneObjectPart part = m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart(ent.UUID);
198 305
199 if (part != null && part.ContainsScripts()) objtype |= 0x08; // Scripted. It COULD have one hidden ... 306 if (part.ContainsScripts())
200 307 {
201 if (((ts.type & objtype) != 0) || ((ts.type & objtype) == ts.type)) 308 objtype |= ACTIVE | SCRIPTED; // Scripted and active. It COULD have one hidden ...
309 }
310 else
202 { 311 {
203 // docs claim AGENT|ACTIVE should find agent objects OR active objects 312 if (ent.Velocity.Equals(ZeroVector))
204 // so the bitwise AND with object type should be non-zero 313 {
314 objtype |= PASSIVE; // Passive non-moving
315 }
316 else
317 {
318 objtype |= ACTIVE; // moving so active
319 }
320 }
205 321
322 // If any of the objects attributes match any in the requested scan type
323 if (((ts.type & objtype) != 0))
324 {
206 // Right type too, what about the other params , key and name ? 325 // Right type too, what about the other params , key and name ?
207 bool keep = true;
208 if (ts.arc < Math.PI) 326 if (ts.arc < Math.PI)
209 { 327 {
210 // not omni-directional. Can you see it ? 328 // not omni-directional. Can you see it ?
@@ -230,67 +348,118 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
230 if (ang_obj > ts.arc) keep = false; 348 if (ang_obj > ts.arc) keep = false;
231 } 349 }
232 350
233 if (keep && (ts.keyID != UUID.Zero) && (ts.keyID != ent.UUID)) 351 if (keep == true)
234 { 352 {
235 keep = false; 353 // add distance for sorting purposes later
354 SensedObjects.Add(new LSL_Types.LSLFloat(dis));
355 SensedObjects.Add(ent.UUID);
236 } 356 }
237
238 if (keep && (ts.name.Length > 0))
239 {
240 if (ts.name != ent.Name)
241 {
242 keep = false;
243 }
244 }
245
246 if (keep == true) SensedObjects.Add(ent.UUID);
247 } 357 }
248 } 358 }
249 } 359 }
360 }
250 361
251 lock (SenseLock) 362 private void doAgentSensor(SenseRepeatClass ts, LSL_Types.list SensedObjects)
363 {
364 List<ScenePresence> Presences;
365
366 // If this is an avatar sense by key try to get them directly
367 // rather than getting a list to scan through
368 if (ts.keyID != UUID.Zero)
252 { 369 {
253 // Create object if it doesn't exist 370 ScenePresence p = m_CmdManager.m_ScriptEngine.World.GetScenePresence(ts.keyID);
254 if (SenseEvents.ContainsKey(ts.localID) == false) 371 if (p == null)
255 { 372 return;
256 SenseEvents.Add(ts.localID, new Dictionary<UUID, LSL_Types.list>()); 373 Presences = new List<ScenePresence>();
257 } 374 Presences.Add(p);
258 // clear if previous traces exist 375 }
259 Dictionary<UUID, LSL_Types.list> Obj; 376 else
260 SenseEvents.TryGetValue(ts.localID, out Obj); 377 {
261 if (Obj.ContainsKey(ts.itemID) == true) 378 Presences = m_CmdManager.m_ScriptEngine.World.GetScenePresences();
262 Obj.Remove(ts.itemID); 379 }
263 380
264 // note list may be zero length 381 // If nobody about quit fast
265 Obj.Add(ts.itemID, SensedObjects); 382 if (Presences.Count == 0)
383 return;
266 384
267 if (SensedObjects.Length == 0) 385 SceneObjectPart SensePoint = ts.host;
268 { 386
269 // send a "no_sensor" 387 Vector3 sensorPos = SensePoint.AbsolutePosition;
270 // Add it to queue 388 Vector3 regionPos = new Vector3(m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocX * Constants.RegionSize, m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
271 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, 389 Vector3 fromRegionPos = sensorPos + regionPos;
272 new EventParams("no_sensor", new Object[0], 390
273 new DetectParams[0])); 391 Quaternion q = SensePoint.RotationOffset;
274 } 392 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
275 else 393 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
394 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
395
396 bool attached = (SensePoint.AttachmentPoint != 0);
397 bool nameSearch = (ts.name != null && ts.name != "");
398
399 foreach (ScenePresence presence in Presences)
400 {
401 bool keep = true;
402
403 if (presence.IsDeleted)
404 continue;
405
406 if (presence.IsChildAgent)
407 keep = false;
408
409 Vector3 toRegionPos = presence.AbsolutePosition + regionPos;
410 double dis = Math.Abs(Util.GetDistanceTo(toRegionPos, fromRegionPos));
411
412 // are they in range
413 if (keep && dis <= ts.range)
276 { 414 {
277 DetectParams[] detect = 415 // if the object the script is in is attached and the avatar is the owner
278 new DetectParams[SensedObjects.Length]; 416 // then this one is not wanted
417 if (attached && presence.UUID == SensePoint.OwnerID)
418 keep = false;
279 419
280 int idx; 420 // check the name if needed
281 for (idx = 0; idx < SensedObjects.Length; idx++) 421 if (keep && nameSearch && ts.name != presence.Name)
422 keep = false;
423
424 // Are they in the required angle of view
425 if (keep && ts.arc < Math.PI)
282 { 426 {
283 detect[idx] = new DetectParams(); 427 // not omni-directional. Can you see it ?
284 detect[idx].Key=(UUID)(SensedObjects.Data[idx]); 428 // vec forward_dir = llRot2Fwd(llGetRot())
285 detect[idx].Populate(m_CmdManager.m_ScriptEngine.World); 429 // vec obj_dir = toRegionPos-fromRegionPos
430 // dot=dot(forward_dir,obj_dir)
431 // mag_fwd = mag(forward_dir)
432 // mag_obj = mag(obj_dir)
433 // ang = acos(dot /(mag_fwd*mag_obj))
434 double ang_obj = 0;
435 try
436 {
437 Vector3 diff = toRegionPos - fromRegionPos;
438 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z);
439 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
440 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
441 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
442 }
443 catch
444 {
445 }
446 if (ang_obj > ts.arc) keep = false;
286 } 447 }
448 }
287 449
288 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, 450 // Do not report gods, not even minor ones
289 new EventParams("sensor", 451 if (keep && presence.GodLevel > 0.0)
290 new Object[] { 452 keep = false;
291 new LSL_Types.LSLInteger(SensedObjects.Length) }, 453
292 detect)); 454 if (keep) // add to list with distance
455 {
456 SensedObjects.Add(new LSL_Types.LSLFloat(dis));
457 SensedObjects.Add(presence.UUID);
293 } 458 }
459
460 // If this is a search by name and we have just found it then no more to do
461 if (nameSearch && ts.name == presence.Name)
462 return;
294 } 463 }
295 } 464 }
296 465