aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
diff options
context:
space:
mode:
authorlbsa712008-06-24 21:09:49 +0000
committerlbsa712008-06-24 21:09:49 +0000
commit6b7930104bdb845d3b9c085dc04f52b6446f23b1 (patch)
tree05ee45781a455817fa400bb99f30f4d19d4eb1f8 /OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
parentbased on positive feedback on performance of making keys fixed length (diff)
downloadopensim-SC_OLD-6b7930104bdb845d3b9c085dc04f52b6446f23b1.zip
opensim-SC_OLD-6b7930104bdb845d3b9c085dc04f52b6446f23b1.tar.gz
opensim-SC_OLD-6b7930104bdb845d3b9c085dc04f52b6446f23b1.tar.bz2
opensim-SC_OLD-6b7930104bdb845d3b9c085dc04f52b6446f23b1.tar.xz
* Applied patch from Melanie, mantis issue #1581 - "Refactor LSL language, api and compiler out of XEngine"
"First stage in a major Script Engine refactor, that will result in the LSL implementaions ebing reconverged. Not there yet, but one major part is done." Thank you, Melanie!
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs389
1 files changed, 389 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
new file mode 100644
index 0000000..5833512
--- /dev/null
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -0,0 +1,389 @@
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 OpenSim 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 libsecondlife;
31using OpenSim.Framework;
32using OpenSim.Region.Environment.Scenes;
33using OpenSim.Region.ScriptEngine.Shared;
34using OpenSim.Region.ScriptEngine.Shared.Api;
35
36namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
37{
38 public class SensorRepeat
39 {
40 public AsyncCommandManager m_CmdManager;
41
42 public SensorRepeat(AsyncCommandManager CmdManager)
43 {
44 m_CmdManager = CmdManager;
45 }
46
47 public Dictionary<uint, Dictionary<LLUUID, LSL_Types.list>> SenseEvents =
48 new Dictionary<uint, Dictionary<LLUUID, LSL_Types.list>>();
49 private Object SenseLock = new Object();
50
51 //
52 // SenseRepeater and Sensors
53 //
54 private class SenseRepeatClass
55 {
56 public uint localID;
57 public LLUUID itemID;
58 public double interval;
59 public DateTime next;
60
61 public string name;
62 public LLUUID keyID;
63 public int type;
64 public double range;
65 public double arc;
66 public SceneObjectPart host;
67 }
68
69 private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>();
70 private object SenseRepeatListLock = new object();
71
72 public void SetSenseRepeatEvent(uint m_localID, LLUUID m_itemID,
73 string name, LLUUID keyID, int type, double range,
74 double arc, double sec, SceneObjectPart host)
75 {
76 // Always remove first, in case this is a re-set
77 UnSetSenseRepeaterEvents(m_localID, m_itemID);
78 if (sec == 0) // Disabling timer
79 return;
80
81 // Add to timer
82 SenseRepeatClass ts = new SenseRepeatClass();
83 ts.localID = m_localID;
84 ts.itemID = m_itemID;
85 ts.interval = sec;
86 ts.name = name;
87 ts.keyID = keyID;
88 ts.type = type;
89 ts.range = range;
90 ts.arc = arc;
91 ts.host = host;
92
93 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
94 lock (SenseRepeatListLock)
95 {
96 SenseRepeaters.Add(ts);
97 }
98 }
99
100 public void UnSetSenseRepeaterEvents(uint m_localID, LLUUID m_itemID)
101 {
102 // Remove from timer
103 lock (SenseRepeatListLock)
104 {
105 List<SenseRepeatClass> NewSensors = new List<SenseRepeatClass>();
106 foreach (SenseRepeatClass ts in SenseRepeaters)
107 {
108 if (ts.localID != m_localID && ts.itemID != m_itemID)
109 {
110 NewSensors.Add(ts);
111 }
112 }
113 SenseRepeaters.Clear();
114 SenseRepeaters = NewSensors;
115 }
116 }
117
118 public void CheckSenseRepeaterEvents()
119 {
120 // Nothing to do here?
121 if (SenseRepeaters.Count == 0)
122 return;
123
124 lock (SenseRepeatListLock)
125 {
126 // Go through all timers
127 foreach (SenseRepeatClass ts in SenseRepeaters)
128 {
129 // Time has passed?
130 if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
131 {
132 SensorSweep(ts);
133 // set next interval
134 ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
135 }
136 }
137 } // lock
138 }
139
140 public void SenseOnce(uint m_localID, LLUUID m_itemID,
141 string name, LLUUID keyID, int type,
142 double range, double arc, SceneObjectPart host)
143 {
144 // Add to timer
145 SenseRepeatClass ts = new SenseRepeatClass();
146 ts.localID = m_localID;
147 ts.itemID = m_itemID;
148 ts.interval = 0;
149 ts.name = name;
150 ts.keyID = keyID;
151 ts.type = type;
152 ts.range = range;
153 ts.arc = arc;
154 ts.host = host;
155 SensorSweep(ts);
156 }
157
158 public LSL_Types.list GetSensorList(uint m_localID, LLUUID m_itemID)
159 {
160 lock (SenseLock)
161 {
162 Dictionary<LLUUID, LSL_Types.list> Obj = null;
163 if (!SenseEvents.TryGetValue(m_localID, out Obj))
164 {
165 return null;
166 }
167 lock (Obj)
168 {
169 // Get script
170 LSL_Types.list SenseList = null;
171 if (!Obj.TryGetValue(m_itemID, out SenseList))
172 {
173 return null;
174 }
175 return SenseList;
176 }
177 }
178 }
179
180 private void SensorSweep(SenseRepeatClass ts)
181 {
182 SceneObjectPart SensePoint = ts.host;
183
184 if (SensePoint == null)
185 {
186 return;
187 }
188
189 LLVector3 sensorPos = SensePoint.AbsolutePosition;
190 LLVector3 regionPos = new LLVector3(m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocX * Constants.RegionSize, m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
191 LLVector3 fromRegionPos = sensorPos + regionPos;
192
193 LLQuaternion q = SensePoint.RotationOffset;
194 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
195 LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
196 double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
197
198 // Here we should do some smart culling ...
199 // math seems quicker than strings so try that first
200 LSL_Types.list SensedObjects = new LSL_Types.list();
201 LSL_Types.Vector3 ZeroVector = new LSL_Types.Vector3(0, 0, 0);
202
203 foreach (EntityBase ent in m_CmdManager.m_ScriptEngine.World.Entities.Values)
204 {
205 LLVector3 toRegionPos = ent.AbsolutePosition + regionPos;
206 double dis = Math.Abs((double)Util.GetDistanceTo(toRegionPos, fromRegionPos));
207 if (dis <= ts.range)
208 {
209 // In Range, is it the right Type ?
210 int objtype = 0;
211
212 if (m_CmdManager.m_ScriptEngine.World.GetScenePresence(ent.UUID) != null) objtype |= 0x01; // actor
213 if (ent.Velocity.Equals(ZeroVector))
214 objtype |= 0x04; // passive non-moving
215 else
216 objtype |= 0x02; // active moving
217
218 SceneObjectPart part = m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart(ent.UUID);
219
220 if (part != null && part.ContainsScripts()) objtype |= 0x08; // Scripted. It COULD have one hidden ...
221
222 if (((ts.type & objtype) != 0) || ((ts.type & objtype) == ts.type))
223 {
224 // docs claim AGENT|ACTIVE should find agent objects OR active objects
225 // so the bitwise AND with object type should be non-zero
226
227 // Right type too, what about the other params , key and name ?
228 bool keep = true;
229 if (ts.arc < Math.PI)
230 {
231 // not omni-directional. Can you see it ?
232 // vec forward_dir = llRot2Fwd(llGetRot())
233 // vec obj_dir = toRegionPos-fromRegionPos
234 // dot=dot(forward_dir,obj_dir)
235 // mag_fwd = mag(forward_dir)
236 // mag_obj = mag(obj_dir)
237 // ang = acos(dot /(mag_fwd*mag_obj))
238 double ang_obj = 0;
239 try
240 {
241 LLVector3 diff = toRegionPos - fromRegionPos;
242 LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z);
243 double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
244 double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
245 ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
246 }
247 catch
248 {
249 }
250
251 if (ang_obj > ts.arc) keep = false;
252 }
253
254 if (keep && (ts.keyID != LLUUID.Zero) && (ts.keyID != ent.UUID))
255 {
256 keep = false;
257 }
258
259 if (keep && (ts.name.Length > 0))
260 {
261 string avatarname=null;
262 string objectname=null;
263 string entname =ent.Name;
264
265 // try avatar username surname
266 UserProfileData profile = m_CmdManager.m_ScriptEngine.World.CommsManager.UserService.GetUserProfile(ent.UUID);
267 if (profile != null)
268 {
269 avatarname = profile.FirstName + " " + profile.SurName;
270 }
271 // try an scene object
272 SceneObjectPart SOP = m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart(ent.UUID);
273 if (SOP != null)
274 {
275 objectname = SOP.Name;
276 }
277
278 if ((ts.name != entname) && (ts.name != avatarname) && (ts.name != objectname))
279 {
280 keep = false;
281 }
282 }
283
284 if (keep == true) SensedObjects.Add(ent.UUID);
285 }
286 }
287 }
288
289 lock (SenseLock)
290 {
291 // Create object if it doesn't exist
292 if (SenseEvents.ContainsKey(ts.localID) == false)
293 {
294 SenseEvents.Add(ts.localID, new Dictionary<LLUUID, LSL_Types.list>());
295 }
296 // clear if previous traces exist
297 Dictionary<LLUUID, LSL_Types.list> Obj;
298 SenseEvents.TryGetValue(ts.localID, out Obj);
299 if (Obj.ContainsKey(ts.itemID) == true)
300 Obj.Remove(ts.itemID);
301
302 // note list may be zero length
303 Obj.Add(ts.itemID, SensedObjects);
304
305 if (SensedObjects.Length == 0)
306 {
307 // send a "no_sensor"
308 // Add it to queue
309 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
310 new EventParams("no_sensor", new Object[0],
311 new DetectParams[0]));
312 }
313 else
314 {
315 DetectParams[] detect =
316 new DetectParams[SensedObjects.Length];
317
318 int idx;
319 for (idx = 0; idx < SensedObjects.Length; idx++)
320 {
321 detect[idx] = new DetectParams();
322 detect[idx].Key=(LLUUID)(SensedObjects.Data[idx]);
323 detect[idx].Populate(m_CmdManager.m_ScriptEngine.World);
324 }
325
326 m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
327 new EventParams("sensor",
328 new Object[] {
329 new LSL_Types.LSLInteger(SensedObjects.Length) },
330 detect));
331 }
332 }
333 }
334
335 public Object[] GetSerializationData(LLUUID itemID)
336 {
337 List<Object> data = new List<Object>();
338
339 foreach (SenseRepeatClass ts in SenseRepeaters)
340 {
341 if (ts.itemID == itemID)
342 {
343 data.Add(ts.interval);
344 data.Add(ts.name);
345 data.Add(ts.keyID);
346 data.Add(ts.type);
347 data.Add(ts.range);
348 data.Add(ts.arc);
349 }
350 }
351 return data.ToArray();
352 }
353
354 public void CreateFromData(uint localID, LLUUID itemID, LLUUID objectID,
355 Object[] data)
356 {
357 SceneObjectPart part =
358 m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart(
359 objectID);
360
361 if (part == null)
362 return;
363
364 int idx = 0;
365
366 while (idx < data.Length)
367 {
368 SenseRepeatClass ts = new SenseRepeatClass();
369
370 ts.localID = localID;
371 ts.itemID = itemID;
372
373 ts.interval = (double)data[idx];
374 ts.name = (string)data[idx+1];
375 ts.keyID = (LLUUID)data[idx+2];
376 ts.type = (int)data[idx+3];
377 ts.range = (double)data[idx+4];
378 ts.arc = (double)data[idx+5];
379 ts.host = part;
380
381 ts.next =
382 DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
383
384 SenseRepeaters.Add(ts);
385 idx += 6;
386 }
387 }
388 }
389}