OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
EventQueueGetModule.cs
Go to the documentation of this file.
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 OpenSimulator 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;
30 using System.Collections.Generic;
31 using System.Net;
32 using System.Reflection;
33 using System.Threading;
34 using log4net;
35 using Nini.Config;
36 using Mono.Addins;
37 using OpenMetaverse;
38 using OpenMetaverse.Messages.Linden;
39 using OpenMetaverse.Packets;
40 using OpenMetaverse.StructuredData;
41 using OpenSim.Framework;
42 using OpenSim.Framework.Console;
43 using OpenSim.Framework.Servers;
44 using OpenSim.Framework.Servers.HttpServer;
45 using OpenSim.Region.Framework.Interfaces;
46 using OpenSim.Region.Framework.Scenes;
47 using BlockingLLSDQueue = OpenSim.Framework.BlockingQueue<OpenMetaverse.StructuredData.OSD>;
49 
50 namespace OpenSim.Region.ClientStack.Linden
51 {
52  public struct QueueItem
53  {
54  public int id;
55  public OSDMap body;
56  }
57 
58  [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EventQueueGetModule")]
60  {
61  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
62  private static string LogHeader = "[EVENT QUEUE GET MODULE]";
63 
67  public int DebugLevel { get; set; }
68 
69  // Viewer post requests timeout in 60 secs
70  // https://bitbucket.org/lindenlab/viewer-release/src/421c20423df93d650cc305dc115922bb30040999/indra/llmessage/llhttpclient.cpp?at=default#cl-44
71  //
72  private const int VIEWER_TIMEOUT = 60 * 1000;
73  // Just to be safe, we work on a 10 sec shorter cycle
74  private const int SERVER_EQ_TIME_NO_EVENTS = VIEWER_TIMEOUT - (10 * 1000);
75 
76  protected Scene m_scene;
77 
78  private Dictionary<UUID, int> m_ids = new Dictionary<UUID, int>();
79 
80  private Dictionary<UUID, Queue<OSD>> queues = new Dictionary<UUID, Queue<OSD>>();
81  private Dictionary<UUID, UUID> m_AvatarQueueUUIDMapping = new Dictionary<UUID, UUID>();
82 
83  #region INonSharedRegionModule methods
84  public virtual void Initialise(IConfigSource config)
85  {
86  }
87 
88  public void AddRegion(Scene scene)
89  {
90  m_scene = scene;
91  scene.RegisterModuleInterface<IEventQueue>(this);
92 
93  scene.EventManager.OnClientClosed += ClientClosed;
94  scene.EventManager.OnRegisterCaps += OnRegisterCaps;
95 
96  MainConsole.Instance.Commands.AddCommand(
97  "Debug",
98  false,
99  "debug eq",
100  "debug eq [0|1|2]",
101  "Turn on event queue debugging\n"
102  + " <= 0 - turns off all event queue logging\n"
103  + " >= 1 - turns on event queue setup and outgoing event logging\n"
104  + " >= 2 - turns on poll notification",
105  HandleDebugEq);
106 
107  MainConsole.Instance.Commands.AddCommand(
108  "Debug",
109  false,
110  "show eq",
111  "show eq",
112  "Show contents of event queues for logged in avatars. Used for debugging.",
113  HandleShowEq);
114  }
115 
116  public void RemoveRegion(Scene scene)
117  {
118  if (m_scene != scene)
119  return;
120 
121  scene.EventManager.OnClientClosed -= ClientClosed;
122  scene.EventManager.OnRegisterCaps -= OnRegisterCaps;
123 
124  scene.UnregisterModuleInterface<IEventQueue>(this);
125  m_scene = null;
126  }
127 
128  public void RegionLoaded(Scene scene)
129  {
130  }
131 
132  public virtual void Close()
133  {
134  }
135 
136  public virtual string Name
137  {
138  get { return "EventQueueGetModule"; }
139  }
140 
141  public Type ReplaceableInterface
142  {
143  get { return null; }
144  }
145 
146  #endregion
147 
148  protected void HandleDebugEq(string module, string[] args)
149  {
150  int debugLevel;
151 
152  if (!(args.Length == 3 && int.TryParse(args[2], out debugLevel)))
153  {
154  MainConsole.Instance.OutputFormat("Usage: debug eq [0|1|2]");
155  }
156  else
157  {
158  DebugLevel = debugLevel;
159  MainConsole.Instance.OutputFormat(
160  "Set event queue debug level to {0} in {1}", DebugLevel, m_scene.RegionInfo.RegionName);
161  }
162  }
163 
164  protected void HandleShowEq(string module, string[] args)
165  {
166  MainConsole.Instance.OutputFormat("For scene {0}", m_scene.Name);
167 
168  lock (queues)
169  {
170  foreach (KeyValuePair<UUID, Queue<OSD>> kvp in queues)
171  {
172  MainConsole.Instance.OutputFormat(
173  "For agent {0} there are {1} messages queued for send.",
174  kvp.Key, kvp.Value.Count);
175  }
176  }
177  }
178 
184  private Queue<OSD> TryGetQueue(UUID agentId)
185  {
186  lock (queues)
187  {
188  if (!queues.ContainsKey(agentId))
189  {
190  if (DebugLevel > 0)
191  m_log.DebugFormat(
192  "[EVENTQUEUE]: Adding new queue for agent {0} in region {1}",
193  agentId, m_scene.RegionInfo.RegionName);
194 
195  queues[agentId] = new Queue<OSD>();
196  }
197 
198  return queues[agentId];
199  }
200  }
201 
203 
208  private Queue<OSD> GetQueue(UUID agentId)
209  {
210  lock (queues)
211  {
212  if (queues.ContainsKey(agentId))
213  {
214  return queues[agentId];
215  }
216  else
217  return null;
218  }
219  }
220 
221  #region IEventQueue Members
222 
223  public bool Enqueue(OSD ev, UUID avatarID)
224  {
225  //m_log.DebugFormat("[EVENTQUEUE]: Enqueuing event for {0} in region {1}", avatarID, m_scene.RegionInfo.RegionName);
226  try
227  {
228  Queue<OSD> queue = GetQueue(avatarID);
229  if (queue != null)
230  {
231  lock (queue)
232  queue.Enqueue(ev);
233  }
234  else
235  {
236  OSDMap evMap = (OSDMap)ev;
237  m_log.WarnFormat(
238  "[EVENTQUEUE]: (Enqueue) No queue found for agent {0} when placing message {1} in region {2}",
239  avatarID, evMap["message"], m_scene.Name);
240  }
241  }
242  catch (NullReferenceException e)
243  {
244  m_log.Error("[EVENTQUEUE] Caught exception: " + e);
245  return false;
246  }
247 
248  return true;
249  }
250 
251  #endregion
252 
253  private void ClientClosed(UUID agentID, Scene scene)
254  {
255  //m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
256 
257  lock (queues)
258  queues.Remove(agentID);
259 
260  lock (m_AvatarQueueUUIDMapping)
261  m_AvatarQueueUUIDMapping.Remove(agentID);
262 
263  lock (m_ids)
264  {
265  if (!m_ids.ContainsKey(agentID))
266  m_ids.Remove(agentID);
267  }
268 
269  // m_log.DebugFormat("[EVENTQUEUE]: Deleted queues for {0} in region {1}", agentID, m_scene.RegionInfo.RegionName);
270 
271  }
272 
277  private string GenerateEqgCapPath(UUID eqgUuid)
278  {
279  return string.Format("/CAPS/EQG/{0}/", eqgUuid);
280  }
281 
282  public void OnRegisterCaps(UUID agentID, Caps caps)
283  {
284  // Register an event queue for the client
285 
286  if (DebugLevel > 0)
287  m_log.DebugFormat(
288  "[EVENTQUEUE]: OnRegisterCaps: agentID {0} caps {1} region {2}",
289  agentID, caps, m_scene.RegionInfo.RegionName);
290 
291  UUID eventQueueGetUUID;
292  Queue<OSD> queue;
293  Random rnd = new Random(Environment.TickCount);
294  int nrnd = rnd.Next(30000000);
295  if (nrnd < 0)
296  nrnd = -nrnd;
297 
298  lock (queues)
299  {
300  if (queues.ContainsKey(agentID))
301  queue = queues[agentID];
302  else
303  queue = null;
304 
305  if (queue == null)
306  {
307  queue = new Queue<OSD>();
308  queues[agentID] = queue;
309 
310  // push markers to handle old responses still waiting
311  // this will cost at most viewer getting two forced noevents
312  // even being a new queue better be safe
313  queue.Enqueue(null);
314  queue.Enqueue(null); // one should be enough
315 
316  lock (m_AvatarQueueUUIDMapping)
317  {
318  eventQueueGetUUID = UUID.Random();
319  if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
320  {
321  // oops this should not happen ?
322  m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID without a queue");
323  eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
324  }
325  m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
326  }
327  lock (m_ids)
328  {
329  if (!m_ids.ContainsKey(agentID))
330  m_ids.Add(agentID, nrnd);
331  else
332  m_ids[agentID] = nrnd;
333  }
334  }
335  else
336  {
337  // push markers to handle old responses still waiting
338  // this will cost at most viewer getting two forced noevents
339  // even being a new queue better be safe
340  queue.Enqueue(null);
341  queue.Enqueue(null); // one should be enough
342 
343  // reuse or not to reuse TODO FIX
344  lock (m_AvatarQueueUUIDMapping)
345  {
346  // Reuse open queues. The client does!
347  // Its reuse caps path not queues those are been reused already
348  if (m_AvatarQueueUUIDMapping.ContainsKey(agentID))
349  {
350  m_log.DebugFormat("[EVENTQUEUE]: Found Existing UUID!");
351  eventQueueGetUUID = m_AvatarQueueUUIDMapping[agentID];
352  }
353  else
354  {
355  eventQueueGetUUID = UUID.Random();
356  m_AvatarQueueUUIDMapping.Add(agentID, eventQueueGetUUID);
357  m_log.DebugFormat("[EVENTQUEUE]: Using random UUID!");
358  }
359  }
360  lock (m_ids)
361  {
362  // change to negative numbers so they are changed at end of sending first marker
363  // old data on a queue may be sent on a response for a new caps
364  // but at least will be sent with coerent IDs
365  if (!m_ids.ContainsKey(agentID))
366  m_ids.Add(agentID, -nrnd); // should not happen
367  else
368  m_ids[agentID] = -m_ids[agentID];
369  }
370  }
371  }
372 
373  caps.RegisterPollHandler(
374  "EventQueueGet",
375  new PollServiceEventArgs(null, GenerateEqgCapPath(eventQueueGetUUID), HasEvents, GetEvents, NoEvents, agentID, SERVER_EQ_TIME_NO_EVENTS));
376  }
377 
378  public bool HasEvents(UUID requestID, UUID agentID)
379  {
380  Queue<OSD> queue = GetQueue(agentID);
381  if (queue != null)
382  lock (queue)
383  {
384  //m_log.WarnFormat("POLLED FOR EVENTS BY {0} in {1} -- {2}", agentID, m_scene.RegionInfo.RegionName, queue.Count);
385  return queue.Count > 0;
386  }
387 
388  //m_log.WarnFormat("POLLED FOR EVENTS BY {0} unknown agent", agentID);
389  return true;
390  }
391 
396  private void LogOutboundDebugMessage(OSD element, UUID agentId)
397  {
398  if (element is OSDMap)
399  {
400  OSDMap ev = (OSDMap)element;
401  m_log.DebugFormat(
402  "Eq OUT {0,-30} to {1,-20} {2,-20}",
403  ev["message"], m_scene.GetScenePresence(agentId).Name, m_scene.Name);
404  }
405  }
406 
407  public Hashtable GetEvents(UUID requestID, UUID pAgentId)
408  {
409  if (DebugLevel >= 2)
410  m_log.WarnFormat("POLLED FOR EQ MESSAGES BY {0} in {1}", pAgentId, m_scene.Name);
411 
412  Queue<OSD> queue = GetQueue(pAgentId);
413  if (queue == null)
414  {
415  return NoEvents(requestID, pAgentId);
416  }
417 
418  OSD element = null;;
419  OSDArray array = new OSDArray();
420  int thisID = 0;
421  bool negativeID = false;
422 
423  lock (queue)
424  {
425  if (queue.Count == 0)
426  return NoEvents(requestID, pAgentId);
427 
428  lock (m_ids)
429  thisID = m_ids[pAgentId];
430 
431  if (thisID < 0)
432  {
433  negativeID = true;
434  thisID = -thisID;
435  }
436 
437  while (queue.Count > 0)
438  {
439  element = queue.Dequeue();
440  // add elements until a marker is found
441  // so they get into a response
442  if (element == null)
443  break;
444  if (DebugLevel > 0)
445  LogOutboundDebugMessage(element, pAgentId);
446  array.Add(element);
447  thisID++;
448  }
449  }
450 
451  OSDMap events = null;
452 
453  if (array.Count > 0)
454  {
455  events = new OSDMap();
456  events.Add("events", array);
457  events.Add("id", new OSDInteger(thisID));
458  }
459 
460  if (negativeID && element == null)
461  {
462  Random rnd = new Random(Environment.TickCount);
463  thisID = rnd.Next(30000000);
464  if (thisID < 0)
465  thisID = -thisID;
466  }
467 
468  lock (m_ids)
469  {
470  m_ids[pAgentId] = thisID + 1;
471  }
472 
473  // if there where no elements before a marker send a NoEvents
474  if (array.Count == 0)
475  return NoEvents(requestID, pAgentId);
476 
477  Hashtable responsedata = new Hashtable();
478  responsedata["int_response_code"] = 200;
479  responsedata["content_type"] = "application/xml";
480  responsedata["keepalive"] = false;
481  responsedata["reusecontext"] = false;
482  responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(events);
483  //m_log.DebugFormat("[EVENTQUEUE]: sending response for {0} in region {1}: {2}", pAgentId, m_scene.RegionInfo.RegionName, responsedata["str_response_string"]);
484  return responsedata;
485  }
486 
487  public Hashtable NoEvents(UUID requestID, UUID agentID)
488  {
489  Hashtable responsedata = new Hashtable();
490  responsedata["int_response_code"] = 502;
491  responsedata["content_type"] = "text/plain";
492  responsedata["keepalive"] = false;
493  responsedata["reusecontext"] = false;
494  responsedata["str_response_string"] = "<llsd></llsd>";
495  responsedata["error_status_text"] = "<llsd></llsd>";
496  responsedata["http_protocol_version"] = "HTTP/1.0";
497  return responsedata;
498  }
499 
500  public void DisableSimulator(ulong handle, UUID avatarID)
501  {
502  OSD item = EventQueueHelper.DisableSimulator(handle);
503  Enqueue(item, avatarID);
504  }
505 
506  public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
507  {
508  if (DebugLevel > 0)
509  m_log.DebugFormat("{0} EnableSimulator. handle={1}, endPoint={2}, avatarID={3}",
510  LogHeader, handle, endPoint, avatarID, regionSizeX, regionSizeY);
511 
512  OSD item = EventQueueHelper.EnableSimulator(handle, endPoint, regionSizeX, regionSizeY);
513  Enqueue(item, avatarID);
514  }
515 
516  public virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath,
517  ulong regionHandle, int regionSizeX, int regionSizeY)
518  {
519  if (DebugLevel > 0)
520  m_log.DebugFormat("{0} EstablishAgentCommunication. handle={1}, endPoint={2}, avatarID={3}",
521  LogHeader, regionHandle, endPoint, avatarID, regionSizeX, regionSizeY);
522 
523  OSD item = EventQueueHelper.EstablishAgentCommunication(avatarID, endPoint.ToString(), capsPath, regionHandle, regionSizeX, regionSizeY);
524  Enqueue(item, avatarID);
525  }
526 
527  public virtual void TeleportFinishEvent(ulong regionHandle, byte simAccess,
528  IPEndPoint regionExternalEndPoint,
529  uint locationID, uint flags, string capsURL,
530  UUID avatarID, int regionSizeX, int regionSizeY)
531  {
532  if (DebugLevel > 0)
533  m_log.DebugFormat("{0} TeleportFinishEvent. handle={1}, endPoint={2}, avatarID={3}",
534  LogHeader, regionHandle, regionExternalEndPoint, avatarID, regionSizeX, regionSizeY);
535 
536  OSD item = EventQueueHelper.TeleportFinishEvent(regionHandle, simAccess, regionExternalEndPoint,
537  locationID, flags, capsURL, avatarID, regionSizeX, regionSizeY);
538  Enqueue(item, avatarID);
539  }
540 
541  public virtual void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt,
542  IPEndPoint newRegionExternalEndPoint,
543  string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
544  {
545  if (DebugLevel > 0)
546  m_log.DebugFormat("{0} CrossRegion. handle={1}, avatarID={2}, regionSize={3},{4}>",
547  LogHeader, handle, avatarID, regionSizeX, regionSizeY);
548 
549  OSD item = EventQueueHelper.CrossRegion(handle, pos, lookAt, newRegionExternalEndPoint,
550  capsURL, avatarID, sessionID, regionSizeX, regionSizeY);
551  Enqueue(item, avatarID);
552  }
553 
554  public void ChatterboxInvitation(UUID sessionID, string sessionName,
555  UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog,
556  uint timeStamp, bool offline, int parentEstateID, Vector3 position,
557  uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
558  {
559  OSD item = EventQueueHelper.ChatterboxInvitation(sessionID, sessionName, fromAgent, message, toAgent, fromName, dialog,
560  timeStamp, offline, parentEstateID, position, ttl, transactionID,
561  fromGroup, binaryBucket);
562  Enqueue(item, toAgent);
563  //m_log.InfoFormat("########### eq ChatterboxInvitation #############\n{0}", item);
564 
565  }
566 
567  public void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat,
568  bool isModerator, bool textMute)
569  {
570  OSD item = EventQueueHelper.ChatterBoxSessionAgentListUpdates(sessionID, fromAgent, canVoiceChat,
571  isModerator, textMute);
572  Enqueue(item, fromAgent);
573  //m_log.InfoFormat("########### eq ChatterBoxSessionAgentListUpdates #############\n{0}", item);
574  }
575 
576  public void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID)
577  {
578  OSD item = EventQueueHelper.ParcelProperties(parcelPropertiesMessage);
579  Enqueue(item, avatarID);
580  }
581 
582  public void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID)
583  {
584  OSD item = EventQueueHelper.GroupMembership(groupUpdate);
585  Enqueue(item, avatarID);
586  }
587 
588  public void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID)
589  {
590  OSD item = EventQueueHelper.PlacesQuery(groupUpdate);
591  Enqueue(item, avatarID);
592  }
593 
594  public OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono)
595  {
596  return EventQueueHelper.ScriptRunningReplyEvent(objectID, itemID, running, mono);
597  }
598 
599  public OSD BuildEvent(string eventName, OSD eventBody)
600  {
601  return EventQueueHelper.BuildEvent(eventName, eventBody);
602  }
603 
604  public void partPhysicsProperties(uint localID, byte physhapetype,
605  float density, float friction, float bounce, float gravmod,UUID avatarID)
606  {
607  OSD item = EventQueueHelper.partPhysicsProperties(localID, physhapetype,
608  density, friction, bounce, gravmod);
609  Enqueue(item, avatarID);
610  }
611  }
612 }
void partPhysicsProperties(uint localID, byte physhapetype, float density, float friction, float bounce, float gravmod, UUID avatarID)
OpenMetaverse.StructuredData.OSDArray OSDArray
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...
OSD ScriptRunningEvent(UUID objectID, UUID itemID, bool running, bool mono)
OpenMetaverse.StructuredData.OSDMap OSDMap
OpenSim.Framework.Capabilities.Caps Caps
virtual void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
void QueryReply(PlacesReplyPacket groupUpdate, UUID avatarID)
Hashtable GetEvents(UUID requestID, UUID pAgentId)
virtual void CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, IPEndPoint newRegionExternalEndPoint, string capsURL, UUID avatarID, UUID sessionID, int regionSizeX, int regionSizeY)
void ChatterboxInvitation(UUID sessionID, string sessionName, UUID fromAgent, string message, UUID toAgent, string fromName, byte dialog, uint timeStamp, bool offline, int parentEstateID, Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket)
void ChatterBoxSessionAgentListUpdates(UUID sessionID, UUID fromAgent, UUID anotherAgent, bool canVoiceChat, bool isModerator, bool textMute)
virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY)
OpenSim.Framework.Capabilities.Caps Caps
OpenMetaverse.StructuredData.OSD OSD
Hashtable NoEvents(UUID requestID, UUID agentID)
void ParcelProperties(ParcelPropertiesMessage parcelPropertiesMessage, UUID avatarID)
virtual void TeleportFinishEvent(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint, uint locationID, uint flags, string capsURL, UUID avatarID, int regionSizeX, int regionSizeY)
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
OpenSim.Framework.BlockingQueue< OpenMetaverse.StructuredData.OSD > BlockingLLSDQueue
virtual void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
void GroupMembership(AgentGroupDataUpdatePacket groupUpdate, UUID avatarID)
virtual void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY)