opensim-development – Blame information for rev 1

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