diff options
author | Teravus Ovares | 2008-05-30 12:27:06 +0000 |
---|---|---|
committer | Teravus Ovares | 2008-05-30 12:27:06 +0000 |
commit | 1a47ff8094ee414a47aebd310826906d89428a09 (patch) | |
tree | 0e90b3a33f43ff8617a077bb57b86d6b28e63e71 /OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs | |
parent | * Fixed a dangling event hook that I added. (diff) | |
download | opensim-SC-1a47ff8094ee414a47aebd310826906d89428a09.zip opensim-SC-1a47ff8094ee414a47aebd310826906d89428a09.tar.gz opensim-SC-1a47ff8094ee414a47aebd310826906d89428a09.tar.bz2 opensim-SC-1a47ff8094ee414a47aebd310826906d89428a09.tar.xz |
* This is Melanie's XEngine script engine. I've not tested this real well, however, it's confirmed to compile and OpenSimulator to run successfully without this script engine active.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs')
-rw-r--r-- | OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs new file mode 100644 index 0000000..5a87bb0 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/XEngine/AsyncCommandPlugins/SensorRepeat.cs | |||
@@ -0,0 +1,391 @@ | |||
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 | |||
28 | using System; | ||
29 | using System.Collections.Generic; | ||
30 | using libsecondlife; | ||
31 | using OpenSim.Framework; | ||
32 | using OpenSim.Region.Environment.Scenes; | ||
33 | using OpenSim.Region.ScriptEngine.XEngine.Script; | ||
34 | |||
35 | namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins | ||
36 | { | ||
37 | public class SensorRepeat | ||
38 | { | ||
39 | public AsyncCommandManager m_CmdManager; | ||
40 | |||
41 | public SensorRepeat(AsyncCommandManager CmdManager) | ||
42 | { | ||
43 | m_CmdManager = CmdManager; | ||
44 | } | ||
45 | |||
46 | public Dictionary<uint, Dictionary<LLUUID, LSL_Types.list>> SenseEvents = | ||
47 | new Dictionary<uint, Dictionary<LLUUID, LSL_Types.list>>(); | ||
48 | private Object SenseLock = new Object(); | ||
49 | |||
50 | // | ||
51 | // SenseRepeater and Sensors | ||
52 | // | ||
53 | private class SenseRepeatClass | ||
54 | { | ||
55 | public uint localID; | ||
56 | public LLUUID itemID; | ||
57 | public double interval; | ||
58 | public DateTime next; | ||
59 | |||
60 | public string name; | ||
61 | public LLUUID keyID; | ||
62 | public int type; | ||
63 | public double range; | ||
64 | public double arc; | ||
65 | public SceneObjectPart host; | ||
66 | } | ||
67 | |||
68 | private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>(); | ||
69 | private object SenseRepeatListLock = new object(); | ||
70 | |||
71 | public void SetSenseRepeatEvent(uint m_localID, LLUUID m_itemID, | ||
72 | string name, LLUUID keyID, int type, double range, double arc, double sec, SceneObjectPart host) | ||
73 | { | ||
74 | Console.WriteLine("SetSensorEvent"); | ||
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 | m_CmdManager.m_ScriptEngine.Log.Info("[AsyncLSL]: GetSensorList missing localID: " + m_localID); | ||
166 | return null; | ||
167 | } | ||
168 | lock (Obj) | ||
169 | { | ||
170 | // Get script | ||
171 | LSL_Types.list SenseList = null; | ||
172 | if (!Obj.TryGetValue(m_itemID, out SenseList)) | ||
173 | { | ||
174 | m_CmdManager.m_ScriptEngine.Log.Info("[AsyncLSL]: GetSensorList missing itemID: " + m_itemID); | ||
175 | return null; | ||
176 | } | ||
177 | return SenseList; | ||
178 | } | ||
179 | } | ||
180 | } | ||
181 | |||
182 | private void SensorSweep(SenseRepeatClass ts) | ||
183 | { | ||
184 | //m_ScriptEngine.Log.Info("[AsyncLSL]:Enter SensorSweep"); | ||
185 | SceneObjectPart SensePoint = ts.host; | ||
186 | |||
187 | if (SensePoint == null) | ||
188 | { | ||
189 | //m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep (SensePoint == null) for "+ts.itemID.ToString()); | ||
190 | return; | ||
191 | } | ||
192 | //m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep Scan"); | ||
193 | |||
194 | LLVector3 sensorPos = SensePoint.AbsolutePosition; | ||
195 | LLVector3 regionPos = new LLVector3(m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocX * Constants.RegionSize, m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocY * Constants.RegionSize, 0); | ||
196 | LLVector3 fromRegionPos = sensorPos + regionPos; | ||
197 | |||
198 | LLQuaternion q = SensePoint.RotationOffset; | ||
199 | LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); | ||
200 | LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); | ||
201 | double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); | ||
202 | |||
203 | // Here we should do some smart culling ... | ||
204 | // math seems quicker than strings so try that first | ||
205 | LSL_Types.list SensedObjects = new LSL_Types.list(); | ||
206 | LSL_Types.Vector3 ZeroVector = new LSL_Types.Vector3(0, 0, 0); | ||
207 | |||
208 | foreach (EntityBase ent in m_CmdManager.m_ScriptEngine.World.Entities.Values) | ||
209 | { | ||
210 | LLVector3 toRegionPos = ent.AbsolutePosition + regionPos; | ||
211 | double dis = Math.Abs((double)Util.GetDistanceTo(toRegionPos, fromRegionPos)); | ||
212 | if (dis <= ts.range) | ||
213 | { | ||
214 | // In Range, is it the right Type ? | ||
215 | int objtype = 0; | ||
216 | |||
217 | if (m_CmdManager.m_ScriptEngine.World.GetScenePresence(ent.UUID) != null) objtype |= 0x01; // actor | ||
218 | if (ent.Velocity.Equals(ZeroVector)) | ||
219 | objtype |= 0x04; // passive non-moving | ||
220 | else | ||
221 | objtype |= 0x02; // active moving | ||
222 | if (ent is IScript) objtype |= 0x08; // Scripted. It COULD have one hidden ... | ||
223 | |||
224 | if (((ts.type & objtype) != 0) || ((ts.type & objtype) == ts.type)) | ||
225 | { | ||
226 | // docs claim AGENT|ACTIVE should find agent objects OR active objects | ||
227 | // so the bitwise AND with object type should be non-zero | ||
228 | |||
229 | // Right type too, what about the other params , key and name ? | ||
230 | bool keep = true; | ||
231 | if (ts.arc < Math.PI) | ||
232 | { | ||
233 | // not omni-directional. Can you see it ? | ||
234 | // vec forward_dir = llRot2Fwd(llGetRot()) | ||
235 | // vec obj_dir = toRegionPos-fromRegionPos | ||
236 | // dot=dot(forward_dir,obj_dir) | ||
237 | // mag_fwd = mag(forward_dir) | ||
238 | // mag_obj = mag(obj_dir) | ||
239 | // ang = acos(dot /(mag_fwd*mag_obj)) | ||
240 | double ang_obj = 0; | ||
241 | try | ||
242 | { | ||
243 | LLVector3 diff = toRegionPos - fromRegionPos; | ||
244 | LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); | ||
245 | double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); | ||
246 | double mag_obj = LSL_Types.Vector3.Mag(obj_dir); | ||
247 | ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); | ||
248 | } | ||
249 | catch | ||
250 | { | ||
251 | } | ||
252 | |||
253 | if (ang_obj > ts.arc) keep = false; | ||
254 | } | ||
255 | |||
256 | if (keep && (ts.keyID != LLUUID.Zero) && (ts.keyID != ent.UUID)) | ||
257 | { | ||
258 | keep = false; | ||
259 | } | ||
260 | |||
261 | if (keep && (ts.name.Length > 0)) | ||
262 | { | ||
263 | string avatarname=null; | ||
264 | string objectname=null; | ||
265 | string entname =ent.Name; | ||
266 | |||
267 | // try avatar username surname | ||
268 | UserProfileData profile = m_CmdManager.m_ScriptEngine.World.CommsManager.UserService.GetUserProfile(ent.UUID); | ||
269 | if (profile != null) | ||
270 | { | ||
271 | avatarname = profile.FirstName + " " + profile.SurName; | ||
272 | } | ||
273 | // try an scene object | ||
274 | SceneObjectPart SOP = m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart(ent.UUID); | ||
275 | if (SOP != null) | ||
276 | { | ||
277 | objectname = SOP.Name; | ||
278 | } | ||
279 | |||
280 | if ((ts.name != entname) && (ts.name != avatarname) && (ts.name != objectname)) | ||
281 | { | ||
282 | keep = false; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | if (keep == true) SensedObjects.Add(ent.UUID); | ||
287 | } | ||
288 | } | ||
289 | } | ||
290 | //m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep SenseLock"); | ||
291 | |||
292 | lock (SenseLock) | ||
293 | { | ||
294 | // Create object if it doesn't exist | ||
295 | if (SenseEvents.ContainsKey(ts.localID) == false) | ||
296 | { | ||
297 | SenseEvents.Add(ts.localID, new Dictionary<LLUUID, LSL_Types.list>()); | ||
298 | } | ||
299 | // clear if previous traces exist | ||
300 | Dictionary<LLUUID, LSL_Types.list> Obj; | ||
301 | SenseEvents.TryGetValue(ts.localID, out Obj); | ||
302 | if (Obj.ContainsKey(ts.itemID) == true) | ||
303 | Obj.Remove(ts.itemID); | ||
304 | |||
305 | // note list may be zero length | ||
306 | Obj.Add(ts.itemID, SensedObjects); | ||
307 | |||
308 | if (SensedObjects.Length == 0) | ||
309 | { | ||
310 | // send a "no_sensor" | ||
311 | // Add it to queue | ||
312 | m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, | ||
313 | new XEventParams("no_sensor", new Object[0], | ||
314 | new XDetectParams[0])); | ||
315 | } | ||
316 | else | ||
317 | { | ||
318 | XDetectParams[] detect = | ||
319 | new XDetectParams[SensedObjects.Length]; | ||
320 | |||
321 | int idx; | ||
322 | for(idx = 0 ; idx < SensedObjects.Length; idx++) | ||
323 | { | ||
324 | detect[idx].Key=(LLUUID)(SensedObjects.Data[idx]); | ||
325 | } | ||
326 | |||
327 | m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID, | ||
328 | new XEventParams("sensor", | ||
329 | new Object[] { | ||
330 | new LSL_Types.LSLInteger(SensedObjects.Length) }, | ||
331 | detect)); | ||
332 | } | ||
333 | } | ||
334 | } | ||
335 | |||
336 | public Object[] GetSerializationData(LLUUID itemID) | ||
337 | { | ||
338 | List<Object> data = new List<Object>(); | ||
339 | |||
340 | foreach (SenseRepeatClass ts in SenseRepeaters) | ||
341 | { | ||
342 | if(ts.itemID == itemID) | ||
343 | { | ||
344 | data.Add(ts.interval); | ||
345 | data.Add(ts.name); | ||
346 | data.Add(ts.keyID); | ||
347 | data.Add(ts.type); | ||
348 | data.Add(ts.range); | ||
349 | data.Add(ts.arc); | ||
350 | } | ||
351 | } | ||
352 | return data.ToArray(); | ||
353 | } | ||
354 | |||
355 | public void CreateFromData(uint localID, LLUUID itemID, LLUUID objectID, | ||
356 | Object[] data) | ||
357 | { | ||
358 | SceneObjectPart part = | ||
359 | m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart( | ||
360 | objectID); | ||
361 | |||
362 | if(part == null) | ||
363 | return; | ||
364 | |||
365 | int idx=0; | ||
366 | |||
367 | while(idx < data.Length) | ||
368 | { | ||
369 | SenseRepeatClass ts = new SenseRepeatClass(); | ||
370 | |||
371 | ts.localID = localID; | ||
372 | ts.itemID = itemID; | ||
373 | |||
374 | ts.interval = (double)data[idx]; | ||
375 | ts.name = (string)data[idx+1]; | ||
376 | ts.keyID = (LLUUID)data[idx+2]; | ||
377 | ts.type = (int)data[idx+3]; | ||
378 | ts.range = (double)data[idx+4]; | ||
379 | ts.arc = (double)data[idx+5]; | ||
380 | ts.host = part; | ||
381 | |||
382 | ts.next = | ||
383 | DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); | ||
384 | |||
385 | SenseRepeaters.Add(ts); | ||
386 | idx += 6; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | } | ||
391 | } | ||