aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Environment/Modules/WorldCommModule.cs
diff options
context:
space:
mode:
authorAdam Frisby2008-04-30 21:16:36 +0000
committerAdam Frisby2008-04-30 21:16:36 +0000
commitf5c312bc3c2567449c7268a54a08a54119f58d53 (patch)
tree424668a4bbec6873ebc5b8256f3671db102f5e9c /OpenSim/Region/Environment/Modules/WorldCommModule.cs
parent* Adds the AuthbuyerID field to sqlite and makes use of it. (diff)
downloadopensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.zip
opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.gz
opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.bz2
opensim-SC-f5c312bc3c2567449c7268a54a08a54119f58d53.tar.xz
* Refactored Environment/Modules directory - modules now reside in their own directory with any associated module-specific classes.
* Each module directory is currently inside one of the following category folders: Agent (Anything relating to do with Client<->Server communications.), Avatar (Anything to do with the avatar or presence inworld), Framework (Classes modules can use), Grid (Grid traffic, new OGS2 grid comms), Scripting (Scripting functions, etc), World (The enrivonment/scene, IE Sun/Tree modules.) * This should be moved into a seperate project file.
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}