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