aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework/Scenes/SceneBase.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework/Scenes/SceneBase.cs')
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs636
1 files changed, 636 insertions, 0 deletions
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
new file mode 100644
index 0000000..7ff3d40
--- /dev/null
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -0,0 +1,636 @@
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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using OpenMetaverse;
33using log4net;
34using Nini.Config;
35using OpenSim.Framework;
36using OpenSim.Framework.Console;
37
38using OpenSim.Region.Framework.Interfaces;
39using GridRegion = OpenSim.Services.Interfaces.GridRegion;
40
41namespace OpenSim.Region.Framework.Scenes
42{
43 public abstract class SceneBase : IScene
44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46
47#pragma warning disable 414
48 private static readonly string LogHeader = "[SCENE]";
49#pragma warning restore 414
50
51 #region Events
52
53 public event restart OnRestart;
54
55 #endregion
56
57 #region Fields
58
59 public string Name { get { return RegionInfo.RegionName; } }
60
61 public IConfigSource Config
62 {
63 get { return GetConfig(); }
64 }
65
66 protected virtual IConfigSource GetConfig()
67 {
68 return null;
69 }
70
71 /// <value>
72 /// All the region modules attached to this scene.
73 /// </value>
74 public Dictionary<string, IRegionModuleBase> RegionModules
75 {
76 get { return m_regionModules; }
77 }
78 private Dictionary<string, IRegionModuleBase> m_regionModules = new Dictionary<string, IRegionModuleBase>();
79
80 /// <value>
81 /// The module interfaces available from this scene.
82 /// </value>
83 protected Dictionary<Type, List<object>> ModuleInterfaces = new Dictionary<Type, List<object>>();
84
85 /// <summary>
86 /// These two objects hold the information about any formats used
87 /// by modules that hold agent specific data.
88 /// </summary>
89 protected List<UUID> FormatsOffered = new List<UUID>();
90 protected Dictionary<object, List<UUID>> FormatsWanted = new Dictionary<object, List<UUID>>();
91
92 protected Dictionary<string, object> ModuleAPIMethods = new Dictionary<string, object>();
93
94 /// <value>
95 /// The module commanders available from this scene
96 /// </value>
97 protected Dictionary<string, ICommander> m_moduleCommanders = new Dictionary<string, ICommander>();
98
99 /// <value>
100 /// Registered classes that are capable of creating entities.
101 /// </value>
102 protected Dictionary<PCode, IEntityCreator> m_entityCreators = new Dictionary<PCode, IEntityCreator>();
103
104 /// <summary>
105 /// The last allocated local prim id. When a new local id is requested, the next number in the sequence is
106 /// dispensed.
107 /// </summary>
108 protected uint m_lastAllocatedLocalId = 720000;
109
110 private readonly Mutex _primAllocateMutex = new Mutex(false);
111
112 protected readonly ClientManager m_clientManager = new ClientManager();
113
114 public bool LoginsEnabled
115 {
116 get
117 {
118 return m_loginsEnabled;
119 }
120
121 set
122 {
123 if (m_loginsEnabled != value)
124 {
125 m_loginsEnabled = value;
126 EventManager.TriggerRegionLoginsStatusChange(this);
127 }
128 }
129 }
130 private bool m_loginsEnabled;
131
132 public bool Ready
133 {
134 get
135 {
136 return m_ready;
137 }
138
139 set
140 {
141 if (m_ready != value)
142 {
143 m_ready = value;
144 EventManager.TriggerRegionReadyStatusChange(this);
145 }
146 }
147 }
148 private bool m_ready;
149
150 public float TimeDilation
151 {
152 get { return 1.0f; }
153 }
154
155 public ITerrainChannel Heightmap;
156
157 /// <value>
158 /// Allows retrieval of land information for this scene.
159 /// </value>
160 public ILandChannel LandChannel;
161
162 /// <value>
163 /// Manage events that occur in this scene (avatar movement, script rez, etc.). Commonly used by region modules
164 /// to subscribe to scene events.
165 /// </value>
166 public EventManager EventManager
167 {
168 get { return m_eventManager; }
169 }
170 protected EventManager m_eventManager;
171
172 protected ScenePermissions m_permissions;
173 public ScenePermissions Permissions
174 {
175 get { return m_permissions; }
176 }
177
178 /* Used by the loadbalancer plugin on GForge */
179 protected RegionStatus m_regStatus;
180 public RegionStatus RegionStatus
181 {
182 get { return m_regStatus; }
183 set { m_regStatus = value; }
184 }
185
186 #endregion
187
188 public SceneBase(RegionInfo regInfo)
189 {
190 RegionInfo = regInfo;
191 }
192
193 #region Update Methods
194
195 /// <summary>
196 /// Called to update the scene loop by a number of frames and until shutdown.
197 /// </summary>
198 /// <param name="frames">
199 /// Number of frames to update. Exits on shutdown even if there are frames remaining.
200 /// If -1 then updates until shutdown.
201 /// </param>
202 /// <returns>true if update completed within minimum frame time, false otherwise.</returns>
203 public abstract bool Update(int frames);
204
205 #endregion
206
207 #region Terrain Methods
208
209 /// <summary>
210 /// Loads the World heightmap
211 /// </summary>
212 public abstract void LoadWorldMap();
213
214 /// <summary>
215 /// Send the region heightmap to the client
216 /// </summary>
217 /// <param name="RemoteClient">Client to send to</param>
218 public virtual void SendLayerData(IClientAPI RemoteClient)
219 {
220 // RemoteClient.SendLayerData(Heightmap.GetFloatsSerialised());
221 ITerrainModule terrModule = RequestModuleInterface<ITerrainModule>();
222 if (terrModule != null)
223 {
224 terrModule.PushTerrain(RemoteClient);
225 }
226 }
227
228 #endregion
229
230 #region Add/Remove Agent/Avatar
231
232 public abstract ISceneAgent AddNewAgent(IClientAPI client, PresenceType type);
233
234 public abstract bool CloseAgent(UUID agentID, bool force);
235
236 public bool TryGetScenePresence(UUID agentID, out object scenePresence)
237 {
238 scenePresence = null;
239 ScenePresence sp = null;
240 if (TryGetScenePresence(agentID, out sp))
241 {
242 scenePresence = sp;
243 return true;
244 }
245
246 return false;
247 }
248
249 /// <summary>
250 /// Try to get a scene presence from the scene
251 /// </summary>
252 /// <param name="agentID"></param>
253 /// <param name="scenePresence">null if there is no scene presence with the given agent id</param>
254 /// <returns>true if there was a scene presence with the given id, false otherwise.</returns>
255 public abstract bool TryGetScenePresence(UUID agentID, out ScenePresence scenePresence);
256
257 #endregion
258
259 /// <summary>
260 ///
261 /// </summary>
262 /// <returns></returns>
263 public virtual RegionInfo RegionInfo { get; private set; }
264
265 #region admin stuff
266
267 public abstract void OtherRegionUp(GridRegion otherRegion);
268
269 public virtual string GetSimulatorVersion()
270 {
271 return "OpenSimulator Server";
272 }
273
274 #endregion
275
276 #region Shutdown
277
278 /// <summary>
279 /// Tidy before shutdown
280 /// </summary>
281 public virtual void Close()
282 {
283 try
284 {
285 EventManager.TriggerShutdown();
286 }
287 catch (Exception e)
288 {
289 m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e));
290 }
291 }
292
293 #endregion
294
295 /// <summary>
296 /// Returns a new unallocated local ID
297 /// </summary>
298 /// <returns>A brand new local ID</returns>
299 public uint AllocateLocalId()
300 {
301 uint myID;
302
303 _primAllocateMutex.WaitOne();
304 myID = ++m_lastAllocatedLocalId;
305 _primAllocateMutex.ReleaseMutex();
306
307 return myID;
308 }
309
310 #region Module Methods
311
312 /// <summary>
313 /// Add a region-module to this scene. TODO: This will replace AddModule in the future.
314 /// </summary>
315 /// <param name="name"></param>
316 /// <param name="module"></param>
317 public void AddRegionModule(string name, IRegionModuleBase module)
318 {
319 if (!RegionModules.ContainsKey(name))
320 {
321 RegionModules.Add(name, module);
322 }
323 }
324
325 public void RemoveRegionModule(string name)
326 {
327 RegionModules.Remove(name);
328 }
329
330 /// <summary>
331 /// Register a module commander.
332 /// </summary>
333 /// <param name="commander"></param>
334 public void RegisterModuleCommander(ICommander commander)
335 {
336 lock (m_moduleCommanders)
337 {
338 m_moduleCommanders.Add(commander.Name, commander);
339 }
340 }
341
342 /// <summary>
343 /// Unregister a module commander and all its commands
344 /// </summary>
345 /// <param name="name"></param>
346 public void UnregisterModuleCommander(string name)
347 {
348 lock (m_moduleCommanders)
349 {
350 ICommander commander;
351 if (m_moduleCommanders.TryGetValue(name, out commander))
352 m_moduleCommanders.Remove(name);
353 }
354 }
355
356 /// <summary>
357 /// Get a module commander
358 /// </summary>
359 /// <param name="name"></param>
360 /// <returns>The module commander, null if no module commander with that name was found</returns>
361 public ICommander GetCommander(string name)
362 {
363 lock (m_moduleCommanders)
364 {
365 if (m_moduleCommanders.ContainsKey(name))
366 return m_moduleCommanders[name];
367 }
368
369 return null;
370 }
371
372 public Dictionary<string, ICommander> GetCommanders()
373 {
374 return m_moduleCommanders;
375 }
376
377 public List<UUID> GetFormatsOffered()
378 {
379 List<UUID> ret = new List<UUID>(FormatsOffered);
380
381 return ret;
382 }
383
384 protected void CheckAndAddAgentDataFormats(object mod)
385 {
386 if (!(mod is IAgentStatefulModule))
387 return;
388
389 IAgentStatefulModule m = (IAgentStatefulModule)mod;
390
391 List<UUID> renderFormats = m.GetRenderStateFormats();
392 List<UUID> acceptFormats = m.GetAcceptStateFormats();
393
394 foreach (UUID render in renderFormats)
395 {
396 if (!(FormatsOffered.Contains(render)))
397 FormatsOffered.Add(render);
398 }
399
400 if (acceptFormats.Count == 0)
401 return;
402
403 if (FormatsWanted.ContainsKey(mod))
404 return;
405
406 FormatsWanted[mod] = acceptFormats;
407 }
408
409 /// <summary>
410 /// Register an interface to a region module. This allows module methods to be called directly as
411 /// well as via events. If there is already a module registered for this interface, it is not replaced
412 /// (is this the best behaviour?)
413 /// </summary>
414 /// <param name="mod"></param>
415 public void RegisterModuleInterface<M>(M mod)
416 {
417// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M));
418
419 List<Object> l = null;
420 if (!ModuleInterfaces.TryGetValue(typeof(M), out l))
421 {
422 l = new List<Object>();
423 ModuleInterfaces.Add(typeof(M), l);
424 }
425
426 if (l.Count > 0)
427 return;
428
429 l.Add(mod);
430
431 CheckAndAddAgentDataFormats(mod);
432
433 if (mod is IEntityCreator)
434 {
435 IEntityCreator entityCreator = (IEntityCreator)mod;
436 foreach (PCode pcode in entityCreator.CreationCapabilities)
437 {
438 m_entityCreators[pcode] = entityCreator;
439 }
440 }
441 }
442
443 public void UnregisterModuleInterface<M>(M mod)
444 {
445 // We can't unregister agent stateful modules because
446 // that would require much more data to be held about formats
447 // and would make that code slower and less efficient.
448 // No known modules are unregistered anyway, ever, unless
449 // the simulator shuts down anyway.
450 if (mod is IAgentStatefulModule)
451 return;
452
453 List<Object> l;
454 if (ModuleInterfaces.TryGetValue(typeof(M), out l))
455 {
456 if (l.Remove(mod))
457 {
458 if (mod is IEntityCreator)
459 {
460 IEntityCreator entityCreator = (IEntityCreator)mod;
461 foreach (PCode pcode in entityCreator.CreationCapabilities)
462 {
463 m_entityCreators[pcode] = null;
464 }
465 }
466 }
467 }
468 }
469
470 public void StackModuleInterface<M>(M mod)
471 {
472 List<Object> l;
473 if (ModuleInterfaces.ContainsKey(typeof(M)))
474 l = ModuleInterfaces[typeof(M)];
475 else
476 l = new List<Object>();
477
478 if (l.Contains(mod))
479 return;
480
481 l.Add(mod);
482
483 CheckAndAddAgentDataFormats(mod);
484
485 if (mod is IEntityCreator)
486 {
487 IEntityCreator entityCreator = (IEntityCreator)mod;
488 foreach (PCode pcode in entityCreator.CreationCapabilities)
489 {
490 m_entityCreators[pcode] = entityCreator;
491 }
492 }
493
494 ModuleInterfaces[typeof(M)] = l;
495 }
496
497 /// <summary>
498 /// For the given interface, retrieve the region module which implements it.
499 /// </summary>
500 /// <returns>null if there is no registered module implementing that interface</returns>
501 public T RequestModuleInterface<T>()
502 {
503 if (ModuleInterfaces.ContainsKey(typeof(T)) &&
504 (ModuleInterfaces[typeof(T)].Count > 0))
505 return (T)ModuleInterfaces[typeof(T)][0];
506 else
507 return default(T);
508 }
509
510 /// <summary>
511 /// For the given interface, retrieve an array of region modules that implement it.
512 /// </summary>
513 /// <returns>an empty array if there are no registered modules implementing that interface</returns>
514 public T[] RequestModuleInterfaces<T>()
515 {
516 if (ModuleInterfaces.ContainsKey(typeof(T)))
517 {
518 List<T> ret = new List<T>();
519
520 foreach (Object o in ModuleInterfaces[typeof(T)])
521 ret.Add((T)o);
522 return ret.ToArray();
523 }
524 else
525 {
526 return new T[] {};
527 }
528 }
529
530 #endregion
531
532 /// <summary>
533 /// Call this from a region module to add a command to the OpenSim console.
534 /// </summary>
535 /// <param name="mod"></param>
536 /// <param name="command"></param>
537 /// <param name="shorthelp"></param>
538 /// <param name="longhelp"></param>
539 /// <param name="callback"></param>
540 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback)
541 {
542 AddCommand(module, command, shorthelp, longhelp, string.Empty, callback);
543 }
544
545 /// <summary>
546 /// Call this from a region module to add a command to the OpenSim console.
547 /// </summary>
548 /// <param name="mod">
549 /// The use of IRegionModuleBase is a cheap trick to get a different method signature,
550 /// though all new modules should be using interfaces descended from IRegionModuleBase anyway.
551 /// </param>
552 /// <param name="category">
553 /// Category of the command. This is the section under which it will appear when the user asks for help
554 /// </param>
555 /// <param name="command"></param>
556 /// <param name="shorthelp"></param>
557 /// <param name="longhelp"></param>
558 /// <param name="callback"></param>
559 public void AddCommand(
560 string category, IRegionModuleBase module, string command, string shorthelp, string longhelp, CommandDelegate callback)
561 {
562 AddCommand(category, module, command, shorthelp, longhelp, string.Empty, callback);
563 }
564
565 /// <summary>
566 /// Call this from a region module to add a command to the OpenSim console.
567 /// </summary>
568 /// <param name="mod"></param>
569 /// <param name="command"></param>
570 /// <param name="shorthelp"></param>
571 /// <param name="longhelp"></param>
572 /// <param name="descriptivehelp"></param>
573 /// <param name="callback"></param>
574 public void AddCommand(IRegionModuleBase module, string command, string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback)
575 {
576 string moduleName = "";
577
578 if (module != null)
579 moduleName = module.Name;
580
581 AddCommand(moduleName, module, command, shorthelp, longhelp, descriptivehelp, callback);
582 }
583
584 /// <summary>
585 /// Call this from a region module to add a command to the OpenSim console.
586 /// </summary>
587 /// <param name="category">
588 /// Category of the command. This is the section under which it will appear when the user asks for help
589 /// </param>
590 /// <param name="mod"></param>
591 /// <param name="command"></param>
592 /// <param name="shorthelp"></param>
593 /// <param name="longhelp"></param>
594 /// <param name="descriptivehelp"></param>
595 /// <param name="callback"></param>
596 public void AddCommand(
597 string category, IRegionModuleBase module, string command,
598 string shorthelp, string longhelp, string descriptivehelp, CommandDelegate callback)
599 {
600 if (MainConsole.Instance == null)
601 return;
602
603 bool shared = false;
604
605 if (module != null)
606 shared = module is ISharedRegionModule;
607
608 MainConsole.Instance.Commands.AddCommand(
609 category, shared, command, shorthelp, longhelp, descriptivehelp, callback);
610 }
611
612 public virtual ISceneObject DeserializeObject(string representation)
613 {
614 return null;
615 }
616
617 public virtual bool AllowScriptCrossings
618 {
619 get { return false; }
620 }
621
622 public virtual void Start()
623 {
624 }
625
626 public void Restart()
627 {
628 // This has to be here to fire the event
629 restart handlerPhysicsCrash = OnRestart;
630 if (handlerPhysicsCrash != null)
631 handlerPhysicsCrash(RegionInfo);
632 }
633
634 public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep);
635 }
636}