aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/WorldCommModule.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Environment/Modules/WorldCommModule.cs')
-rw-r--r--OpenSim/Region/Environment/Modules/WorldCommModule.cs584
1 files changed, 0 insertions, 584 deletions
diff --git a/OpenSim/Region/Environment/Modules/WorldCommModule.cs b/OpenSim/Region/Environment/Modules/WorldCommModule.cs
deleted file mode 100644
index 638deed..0000000
--- a/OpenSim/Region/Environment/Modules/WorldCommModule.cs
+++ /dev/null
@@ -1,584 +0,0 @@
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;
30using libsecondlife;
31using Nini.Config;
32using OpenSim.Framework;
33using OpenSim.Region.Environment.Interfaces;
34using OpenSim.Region.Environment.Scenes;
35
36/*****************************************************
37 *
38 * WorldCommModule
39 *
40 *
41 * Holding place for world comms - basically llListen
42 * function implementation.
43 *
44 * lLListen(integer channel, string name, key id, string msg)
45 * The name, id, and msg arguments specify the filtering
46 * criteria. You can pass the empty string
47 * (or NULL_KEY for id) for these to set a completely
48 * open filter; this causes the listen() event handler to be
49 * invoked for all chat on the channel. To listen only
50 * for chat spoken by a specific object or avatar,
51 * specify the name and/or id arguments. To listen
52 * only for a specific command, specify the
53 * (case-sensitive) msg argument. If msg is not empty,
54 * listener will only hear strings which are exactly equal
55 * to msg. You can also use all the arguments to establish
56 * the most restrictive filtering criteria.
57 *
58 * It might be useful for each listener to maintain a message
59 * digest, with a list of recent messages by UUID. This can
60 * be used to prevent in-world repeater loops. However, the
61 * linden functions do not have this capability, so for now
62 * thats the way it works.
63 *
64 * **************************************************/
65
66namespace OpenSim.Region.Environment.Modules
67{
68 public class WorldCommModule : IRegionModule, IWorldComm
69 {
70 private Scene m_scene;
71 private object CommListLock = new object();
72 private object ListLock = new object();
73 private string m_name = "WorldCommModule";
74 private ListenerManager m_listenerManager;
75 private Queue m_pendingQ;
76 private Queue m_pending;
77
78 public WorldCommModule()
79 {
80 }
81
82 public void Initialise(Scene scene, IConfigSource config)
83 {
84 m_scene = scene;
85 m_scene.RegisterModuleInterface<IWorldComm>(this);
86 m_listenerManager = new ListenerManager();
87 m_scene.EventManager.OnNewClient += NewClient;
88 m_pendingQ = new Queue();
89 m_pending = Queue.Synchronized(m_pendingQ);
90 }
91
92 public void PostInitialise()
93 {
94 }
95
96 public void Close()
97 {
98 }
99
100 public string Name
101 {
102 get { return m_name; }
103 }
104
105 public bool IsSharedModule
106 {
107 get { return false; }
108 }
109
110 public void NewClient(IClientAPI client)
111 {
112 client.OnChatFromViewer += DeliverClientMessage;
113 }
114
115 /********************************************************************
116 *
117 * Listener Stuff
118 *
119 * *****************************************************************/
120 private void DeliverClientMessage(Object sender, ChatFromViewerArgs e)
121 {
122 DeliverMessage(e.Sender.AgentId.ToString(),
123 e.Type, e.Channel,
124 e.Sender.FirstName + " " + e.Sender.LastName,
125 e.Message);
126 }
127
128 public int Listen(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
129 {
130 return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg);
131 }
132
133 public void ListenControl(int handle, int active)
134 {
135 if (m_listenerManager != null)
136 {
137 if (active == 1)
138 m_listenerManager.Activate(handle);
139 else if (active == 0)
140 m_listenerManager.Dectivate(handle);
141 }
142 }
143
144 public void ListenRemove(int handle)
145 {
146 if (m_listenerManager != null)
147 {
148 m_listenerManager.Remove(handle);
149 }
150 }
151
152 public void DeleteListener(LLUUID itemID)
153 {
154 if (m_listenerManager != null)
155 {
156 m_listenerManager.DeleteListener(itemID);
157 }
158 }
159
160 // This method scans nearby objects and determines if they are listeners,
161 // and if so if this message fits the filter. If it does, then
162 // enqueue the message for delivery to the objects listen event handler.
163 // Objects that do an llSay have their messages delivered here, and for
164 // nearby avatars, the SimChat function is used.
165 public void DeliverMessage(string sourceItemID, ChatTypeEnum type, int channel, string name, string msg)
166 {
167 SceneObjectPart source = null;
168 ScenePresence avatar = null;
169
170 source = m_scene.GetSceneObjectPart(new LLUUID(sourceItemID));
171 if (source == null)
172 {
173 avatar = m_scene.GetScenePresence(new LLUUID(sourceItemID));
174 }
175 if ((avatar != null) || (source != null))
176 {
177 // Loop through the objects in the scene
178 // If they are in proximity, then if they are
179 // listeners, if so add them to the pending queue
180
181 foreach (ListenerInfo li in m_listenerManager.GetListeners())
182 {
183 EntityBase sPart;
184
185 m_scene.Entities.TryGetValue(li.GetHostID(), out sPart);
186
187 if (sPart != null)
188 {
189 double dis = 0;
190
191 if (source != null)
192 dis = Util.GetDistanceTo(sPart.AbsolutePosition, source.AbsolutePosition);
193 else
194 dis = Util.GetDistanceTo(sPart.AbsolutePosition, avatar.AbsolutePosition);
195
196 switch (type)
197 {
198 case ChatTypeEnum.Whisper:
199
200 if ((dis < 10) && (dis > -10))
201 {
202 if (li.GetChannel() == channel)
203 {
204 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
205 sourceItemID, sPart.UUID, channel, name, msg
206 );
207 if (isListener != null)
208 {
209 lock (m_pending.SyncRoot)
210 {
211 m_pending.Enqueue(isListener);
212 }
213 }
214 }
215 }
216 break;
217
218 case ChatTypeEnum.Say:
219
220 if ((dis < 30) && (dis > -30))
221 {
222 if (li.GetChannel() == channel)
223 {
224 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
225 sourceItemID, sPart.UUID, channel, name, msg
226 );
227 if (isListener != null)
228 {
229 lock (m_pending.SyncRoot)
230 {
231 m_pending.Enqueue(isListener);
232 }
233 }
234 }
235 }
236 break;
237
238 case ChatTypeEnum.Shout:
239 if ((dis < 100) && (dis > -100))
240 {
241 if (li.GetChannel() == channel)
242 {
243 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
244 sourceItemID, sPart.UUID, channel, name, msg
245 );
246 if (isListener != null)
247 {
248 lock (m_pending.SyncRoot)
249 {
250 m_pending.Enqueue(isListener);
251 }
252 }
253 }
254 }
255 break;
256
257 case ChatTypeEnum.Broadcast:
258 // Dont process if this message is from itself!
259 if (li.GetHostID().ToString().Equals(sourceItemID) ||
260 sPart.UUID.ToString().Equals(sourceItemID))
261 continue;
262
263 if (li.GetChannel() == channel)
264 {
265 ListenerInfo isListener = m_listenerManager.IsListenerMatch(
266 sourceItemID, sPart.UUID, channel, name, msg
267 );
268 if (isListener != null)
269 {
270 lock (m_pending.SyncRoot)
271 {
272 m_pending.Enqueue(isListener);
273 }
274 }
275 }
276
277 break;
278 }
279 }
280 }
281 }
282 }
283
284 public bool HasMessages()
285 {
286 if (m_pending != null)
287 return (m_pending.Count > 0);
288 else
289 return false;
290 }
291
292 public ListenerInfo GetNextMessage()
293 {
294 ListenerInfo li = null;
295
296 lock (m_pending.SyncRoot)
297 {
298 li = (ListenerInfo)m_pending.Dequeue();
299 }
300
301 return li;
302 }
303
304 public uint PeekNextMessageLocalID()
305 {
306 return ((ListenerInfo)m_pending.Peek()).GetLocalID();
307 }
308
309 public LLUUID PeekNextMessageItemID()
310 {
311 return ((ListenerInfo)m_pending.Peek()).GetItemID();
312 }
313 }
314
315 /**********************************************************
316 *
317 * Even more listener stuff
318 *
319 * ********************************************************/
320 public class ListenerManager
321 {
322 //private Dictionary<int, ListenerInfo> m_listeners;
323 private Hashtable m_listeners = Hashtable.Synchronized(new Hashtable());
324 private object ListenersLock = new object();
325 private int m_MaxListeners = 100;
326
327 public int AddListener(uint localID, LLUUID itemID, LLUUID hostID, int channel, string name, string id, string msg)
328 {
329 if (m_listeners.Count < m_MaxListeners)
330 {
331 ListenerInfo isListener = IsListenerMatch(LLUUID.Zero.ToString(), itemID, channel, name, msg);
332
333 if (isListener == null)
334 {
335 int newHandle = GetNewHandle();
336
337 if (newHandle > -1)
338 {
339 ListenerInfo li = new ListenerInfo(localID, newHandle, itemID, hostID, channel, name, id, msg);
340
341 lock (m_listeners.SyncRoot)
342 {
343 m_listeners.Add(newHandle, li);
344 }
345
346 return newHandle;
347 }
348 }
349 }
350
351 return -1;
352 }
353
354 public void Remove(int handle)
355 {
356 lock (m_listeners.SyncRoot)
357 {
358 m_listeners.Remove(handle);
359 }
360 }
361
362 public void DeleteListener(LLUUID itemID)
363 {
364 ArrayList removedListeners = new ArrayList();
365
366 lock (m_listeners.SyncRoot)
367 {
368 IDictionaryEnumerator en = m_listeners.GetEnumerator();
369 while (en.MoveNext())
370 {
371 ListenerInfo li = (ListenerInfo)en.Value;
372 if (li.GetItemID().Equals(itemID))
373 {
374 removedListeners.Add(li.GetHandle());
375 }
376 }
377 foreach (int handle in removedListeners)
378 {
379 m_listeners.Remove(handle);
380 }
381 }
382 }
383
384 private int GetNewHandle()
385 {
386 for (int i = 0; i < int.MaxValue - 1; i++)
387 {
388 if (!m_listeners.ContainsKey(i))
389 return i;
390 }
391
392 return -1;
393 }
394
395 public bool IsListener(LLUUID hostID)
396 {
397 foreach (ListenerInfo li in m_listeners.Values)
398 {
399 if (li.GetHostID().Equals(hostID))
400 return true;
401 }
402
403 return false;
404 }
405
406 public void Activate(int handle)
407 {
408
409 if (m_listeners.ContainsKey(handle))
410 {
411 lock (m_listeners.SyncRoot)
412 {
413 ListenerInfo li = (ListenerInfo)m_listeners[handle];
414 li.Activate();
415 }
416 }
417 }
418
419 public void Dectivate(int handle)
420 {
421
422 if (m_listeners.ContainsKey(handle))
423 {
424 ListenerInfo li = (ListenerInfo)m_listeners[handle];
425 li.Deactivate();
426 }
427 }
428
429 // Theres probably a more clever and efficient way to
430 // do this, maybe with regex.
431 public ListenerInfo IsListenerMatch(string sourceItemID, LLUUID listenerKey, int channel, string name,
432 string msg)
433 {
434 bool isMatch = true;
435 lock (m_listeners.SyncRoot)
436 {
437 IDictionaryEnumerator en = m_listeners.GetEnumerator();
438 while (en.MoveNext())
439 {
440 ListenerInfo li = (ListenerInfo)en.Value;
441
442 if (li.IsActive())
443 {
444 if (li.GetHostID().Equals(listenerKey))
445 {
446 if (channel == li.GetChannel())
447 {
448 if ((li.GetID().ToString().Length > 0) &&
449 (!li.GetID().Equals(LLUUID.Zero)))
450 {
451 if (!li.GetID().ToString().Equals(sourceItemID))
452 {
453 isMatch = false;
454 }
455 }
456 if (isMatch && (li.GetName().Length > 0))
457 {
458 if (li.GetName().Equals(name))
459 {
460 isMatch = false;
461 }
462 }
463 if (isMatch)
464 {
465 return new ListenerInfo(
466 li.GetLocalID(), li.GetHandle(), li.GetItemID(), li.GetHostID(),
467 li.GetChannel(), name, li.GetID(), msg, new LLUUID(sourceItemID)
468 );
469 }
470 }
471 }
472 }
473 }
474 }
475 return null;
476 }
477
478 public ICollection GetListeners()
479 {
480 return m_listeners.Values;
481 }
482 }
483
484 public class ListenerInfo
485 {
486 private LLUUID m_itemID; // ID of the host script engine
487 private LLUUID m_hostID; // ID of the host/scene part
488 private LLUUID m_sourceItemID; // ID of the scenePart or avatar source of the message
489 private int m_channel; // Channel
490 private int m_handle; // Assigned handle of this listener
491 private uint m_localID; // Local ID from script engine
492 private string m_name; // Object name to filter messages from
493 private LLUUID m_id; // ID to filter messages from
494 private string m_message; // The message
495 private bool m_active; // Listener is active or not
496
497 public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id, string message)
498 {
499 Initialise(localID, handle, ItemID, hostID, channel, name, id, message);
500 }
501
502 public ListenerInfo(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name, LLUUID id,
503 string message, LLUUID sourceItemID)
504 {
505 Initialise(localID, handle, ItemID, hostID, channel, name, id, message);
506 m_sourceItemID = sourceItemID;
507 }
508
509 private void Initialise(uint localID, int handle, LLUUID ItemID, LLUUID hostID, int channel, string name,
510 LLUUID id, string message)
511 {
512 m_handle = handle;
513 m_channel = channel;
514 m_itemID = ItemID;
515 m_hostID = hostID;
516 m_name = name;
517 m_id = id;
518 m_message = message;
519 m_active = true;
520 m_localID = localID;
521 }
522
523 public LLUUID GetItemID()
524 {
525 return m_itemID;
526 }
527
528 public LLUUID GetHostID()
529 {
530 return m_hostID;
531 }
532
533 public LLUUID GetSourceItemID()
534 {
535 return m_sourceItemID;
536 }
537
538 public int GetChannel()
539 {
540 return m_channel;
541 }
542
543 public uint GetLocalID()
544 {
545 return m_localID;
546 }
547
548 public int GetHandle()
549 {
550 return m_handle;
551 }
552
553 public string GetMessage()
554 {
555 return m_message;
556 }
557
558 public string GetName()
559 {
560 return m_name;
561 }
562
563 public bool IsActive()
564 {
565 return m_active;
566 }
567
568 public void Deactivate()
569 {
570 m_active = false;
571 }
572
573 public void Activate()
574 {
575 m_active = true;
576 }
577
578 public LLUUID GetID()
579 {
580 return m_id;
581 }
582 }
583
584}