opensim – 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 log4net;
32 using Mono.Addins;
33 using Nini.Config;
34 using OpenMetaverse;
35 using OpenSim.Framework;
36 using OpenSim.Region.Framework.Interfaces;
37 using OpenSim.Region.Framework.Scenes;
38  
39 using OpenSim.Region.CoreModules.World.Wind;
40  
41 namespace OpenSim.Region.CoreModules
42 {
43 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WindModule")]
44 public class WindModule : IWindModule
45 {
46 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47  
48 private uint m_frame = 0;
49 private uint m_frameLastUpdateClientArray = 0;
50 private int m_frameUpdateRate = 150;
51 //private Random m_rndnums = new Random(Environment.TickCount);
52 private Scene m_scene = null;
53 private bool m_ready = false;
54  
55 private bool m_enabled = false;
56 private IConfig m_windConfig;
57 private IWindModelPlugin m_activeWindPlugin = null;
58 private string m_dWindPluginName = "SimpleRandomWind";
59 private Dictionary<string, IWindModelPlugin> m_availableWindPlugins = new Dictionary<string, IWindModelPlugin>();
60  
61 // Simplified windSpeeds based on the fact that the client protocal tracks at a resolution of 16m
62 private Vector2[] windSpeeds = new Vector2[16 * 16];
63  
64 #region INonSharedRegionModule Methods
65  
66 public void Initialise(IConfigSource config)
67 {
68 m_windConfig = config.Configs["Wind"];
69 // string desiredWindPlugin = m_dWindPluginName;
70  
71 if (m_windConfig != null)
72 {
73 m_enabled = m_windConfig.GetBoolean("enabled", true);
74  
75 m_frameUpdateRate = m_windConfig.GetInt("wind_update_rate", 150);
76  
77 // Determine which wind model plugin is desired
78 if (m_windConfig.Contains("wind_plugin"))
79 {
80 m_dWindPluginName = m_windConfig.GetString("wind_plugin", m_dWindPluginName);
81 }
82 }
83  
84 if (m_enabled)
85 {
86 m_log.InfoFormat("[WIND] Enabled with an update rate of {0} frames.", m_frameUpdateRate);
87  
88 }
89  
90 }
91  
92 public void AddRegion(Scene scene)
93 {
94 if (!m_enabled)
95 return;
96  
97 m_scene = scene;
98 m_frame = 0;
99  
100 // Register all the Wind Model Plug-ins
101 foreach (IWindModelPlugin windPlugin in AddinManager.GetExtensionObjects("/OpenSim/WindModule", false))
102 {
103 m_log.InfoFormat("[WIND] Found Plugin: {0}", windPlugin.Name);
104 m_availableWindPlugins.Add(windPlugin.Name, windPlugin);
105 }
106  
107 // Check for desired plugin
108 if (m_availableWindPlugins.ContainsKey(m_dWindPluginName))
109 {
110 m_activeWindPlugin = m_availableWindPlugins[m_dWindPluginName];
111  
112 m_log.InfoFormat("[WIND] {0} plugin found, initializing.", m_dWindPluginName);
113  
114 if (m_windConfig != null)
115 {
116 m_activeWindPlugin.Initialise();
117 m_activeWindPlugin.WindConfig(m_scene, m_windConfig);
118 }
119 }
120  
121  
122 // if the plug-in wasn't found, default to no wind.
123 if (m_activeWindPlugin == null)
124 {
125 m_log.ErrorFormat("[WIND] Could not find specified wind plug-in: {0}", m_dWindPluginName);
126 m_log.ErrorFormat("[WIND] Defaulting to no wind.");
127 }
128  
129 // This one puts an entry in the main help screen
130 // m_scene.AddCommand("Regions", this, "wind", "wind", "Usage: wind <plugin> <param> [value] - Get or Update Wind paramaters", null);
131  
132 // This one enables the ability to type just the base command without any parameters
133 // m_scene.AddCommand("Regions", this, "wind", "", "", HandleConsoleCommand);
134  
135 // Get a list of the parameters for each plugin
136 foreach (IWindModelPlugin windPlugin in m_availableWindPlugins.Values)
137 {
138 // m_scene.AddCommand("Regions", this, String.Format("wind base wind_plugin {0}", windPlugin.Name), String.Format("{0} - {1}", windPlugin.Name, windPlugin.Description), "", HandleConsoleBaseCommand);
139 m_scene.AddCommand(
140 "Regions",
141 this,
142 "wind base wind_update_rate",
143 "wind base wind_update_rate [<value>]",
144 "Get or set the wind update rate.",
145 "",
146 HandleConsoleBaseCommand);
147  
148 foreach (KeyValuePair<string, string> kvp in windPlugin.WindParams())
149 {
150 string windCommand = String.Format("wind {0} {1}", windPlugin.Name, kvp.Key);
151 m_scene.AddCommand("Regions", this, windCommand, string.Format("{0} [<value>]", windCommand), kvp.Value, "", HandleConsoleParamCommand);
152 }
153 }
154  
155 // Register event handlers for when Avatars enter the region, and frame ticks
156 m_scene.EventManager.OnFrame += WindUpdate;
157 m_scene.EventManager.OnMakeRootAgent += OnAgentEnteredRegion;
158  
159 // Register the wind module
160 m_scene.RegisterModuleInterface<IWindModule>(this);
161  
162 // Generate initial wind values
163 GenWindPos();
164  
165 // Mark Module Ready for duty
166 m_ready = true;
167 }
168  
169 public void RemoveRegion(Scene scene)
170 {
171 if (!m_enabled)
172 return;
173  
174 m_ready = false;
175  
176 // REVIEW: If a region module is closed, is there a possibility that it'll re-open/initialize ??
177 m_activeWindPlugin = null;
178 foreach (IWindModelPlugin windPlugin in m_availableWindPlugins.Values)
179 {
180 windPlugin.Dispose();
181 }
182  
183 m_availableWindPlugins.Clear();
184  
185 // Remove our hooks
186 m_scene.EventManager.OnFrame -= WindUpdate;
187 m_scene.EventManager.OnMakeRootAgent -= OnAgentEnteredRegion;
188  
189 }
190  
191 public void Close()
192 {
193 }
194  
195 public string Name
196 {
197 get { return "WindModule"; }
198 }
199  
200 public Type ReplaceableInterface
201 {
202 get { return null; }
203 }
204  
205 public void RegionLoaded(Scene scene)
206 {
207 }
208  
209 #endregion
210  
211 #region Console Commands
212 private void ValidateConsole()
213 {
214 if (m_scene.ConsoleScene() == null)
215 {
216 // FIXME: If console region is root then this will be printed by every module. Currently, there is no
217 // way to prevent this, short of making the entire module shared (which is complete overkill).
218 // One possibility is to return a bool to signal whether the module has completely handled the command
219 MainConsole.Instance.Output("Please change to a specific region in order to set Sun parameters.");
220 return;
221 }
222  
223 if (m_scene.ConsoleScene() != m_scene)
224 {
225 MainConsole.Instance.Output("Console Scene is not my scene.");
226 return;
227 }
228 }
229  
230 /// <summary>
231 /// Base console command handler, only used if a person specifies the base command with now options
232 /// </summary>
233 private void HandleConsoleCommand(string module, string[] cmdparams)
234 {
235 ValidateConsole();
236  
237 MainConsole.Instance.Output(
238 "The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins.");
239 }
240  
241 /// <summary>
242 /// Called to change the active wind model plugin
243 /// </summary>
244 private void HandleConsoleBaseCommand(string module, string[] cmdparams)
245 {
246 ValidateConsole();
247  
248 if ((cmdparams.Length != 4)
249 || !cmdparams[1].Equals("base"))
250 {
251 MainConsole.Instance.Output(
252 "Invalid parameters to change parameters for Wind module base, usage: wind base <parameter> <value>");
253  
254 return;
255 }
256  
257 switch (cmdparams[2])
258 {
259 case "wind_update_rate":
260 int newRate = 1;
261  
262 if (int.TryParse(cmdparams[3], out newRate))
263 {
264 m_frameUpdateRate = newRate;
265 }
266 else
267 {
268 MainConsole.Instance.OutputFormat(
269 "Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]);
270  
271 return;
272 }
273  
274 break;
275 case "wind_plugin":
276 string desiredPlugin = cmdparams[3];
277  
278 if (desiredPlugin.Equals(m_activeWindPlugin.Name))
279 {
280 MainConsole.Instance.OutputFormat("Wind model plugin {0} is already active", cmdparams[3]);
281  
282 return;
283 }
284  
285 if (m_availableWindPlugins.ContainsKey(desiredPlugin))
286 {
287 m_activeWindPlugin = m_availableWindPlugins[cmdparams[3]];
288  
289 MainConsole.Instance.OutputFormat("{0} wind model plugin now active", m_activeWindPlugin.Name);
290 }
291 else
292 {
293 MainConsole.Instance.OutputFormat("Could not find wind model plugin {0}", desiredPlugin);
294 }
295 break;
296 }
297 }
298  
299 /// <summary>
300 /// Called to change plugin parameters.
301 /// </summary>
302 private void HandleConsoleParamCommand(string module, string[] cmdparams)
303 {
304 ValidateConsole();
305  
306 // wind <plugin> <param> [value]
307 if ((cmdparams.Length != 4)
308 && (cmdparams.Length != 3))
309 {
310 MainConsole.Instance.Output("Usage: wind <plugin> <param> [value]");
311 return;
312 }
313  
314 string plugin = cmdparams[1];
315 string param = cmdparams[2];
316 float value = 0f;
317 if (cmdparams.Length == 4)
318 {
319 if (!float.TryParse(cmdparams[3], out value))
320 {
321 MainConsole.Instance.OutputFormat("Invalid value {0}", cmdparams[3]);
322 }
323  
324 try
325 {
326 WindParamSet(plugin, param, value);
327 MainConsole.Instance.OutputFormat("{0} set to {1}", param, value);
328 }
329 catch (Exception e)
330 {
331 MainConsole.Instance.OutputFormat("{0}", e.Message);
332 }
333 }
334 else
335 {
336 try
337 {
338 value = WindParamGet(plugin, param);
339 MainConsole.Instance.OutputFormat("{0} : {1}", param, value);
340 }
341 catch (Exception e)
342 {
343 MainConsole.Instance.OutputFormat("{0}", e.Message);
344 }
345 }
346  
347 }
348 #endregion
349  
350  
351 #region IWindModule Methods
352  
353 /// <summary>
354 /// Retrieve the wind speed at the given region coordinate. This
355 /// implimentation ignores Z.
356 /// </summary>
357 /// <param name="x">0...255</param>
358 /// <param name="y">0...255</param>
359 public Vector3 WindSpeed(int x, int y, int z)
360 {
361 if (m_activeWindPlugin != null)
362 {
363 return m_activeWindPlugin.WindSpeed(x, y, z);
364 }
365 else
366 {
367 return new Vector3(0.0f, 0.0f, 0.0f);
368 }
369 }
370  
371 public void WindParamSet(string plugin, string param, float value)
372 {
373 if (m_availableWindPlugins.ContainsKey(plugin))
374 {
375 IWindModelPlugin windPlugin = m_availableWindPlugins[plugin];
376 windPlugin.WindParamSet(param, value);
377 }
378 else
379 {
380 throw new Exception(String.Format("Could not find plugin {0}", plugin));
381 }
382 }
383  
384 public float WindParamGet(string plugin, string param)
385 {
386 if (m_availableWindPlugins.ContainsKey(plugin))
387 {
388 IWindModelPlugin windPlugin = m_availableWindPlugins[plugin];
389 return windPlugin.WindParamGet(param);
390 }
391 else
392 {
393 throw new Exception(String.Format("Could not find plugin {0}", plugin));
394 }
395 }
396  
397 public string WindActiveModelPluginName
398 {
399 get
400 {
401 if (m_activeWindPlugin != null)
402 {
403 return m_activeWindPlugin.Name;
404 }
405 else
406 {
407 return String.Empty;
408 }
409 }
410 }
411  
412 #endregion
413  
414 /// <summary>
415 /// Called on each frame update. Updates the wind model and clients as necessary.
416 /// </summary>
417 public void WindUpdate()
418 {
419 if (((m_frame++ % m_frameUpdateRate) != 0) || !m_ready)
420 {
421 return;
422 }
423  
424 GenWindPos();
425  
426 SendWindAllClients();
427 }
428  
429 public void OnAgentEnteredRegion(ScenePresence avatar)
430 {
431 if (m_ready)
432 {
433 if (m_activeWindPlugin != null)
434 {
435 // Ask wind plugin to generate a LL wind array to be cached locally
436 // Try not to update this too often, as it may involve array copies
437 if (m_frame >= (m_frameLastUpdateClientArray + m_frameUpdateRate))
438 {
439 windSpeeds = m_activeWindPlugin.WindLLClientArray();
440 m_frameLastUpdateClientArray = m_frame;
441 }
442 }
443  
444 avatar.ControllingClient.SendWindData(windSpeeds);
445 }
446 }
447  
448 private void SendWindAllClients()
449 {
450 if (m_ready)
451 {
452 if (m_scene.GetRootAgentCount() > 0)
453 {
454 // Ask wind plugin to generate a LL wind array to be cached locally
455 // Try not to update this too often, as it may involve array copies
456 if (m_frame >= (m_frameLastUpdateClientArray + m_frameUpdateRate))
457 {
458 windSpeeds = m_activeWindPlugin.WindLLClientArray();
459 m_frameLastUpdateClientArray = m_frame;
460 }
461  
462 m_scene.ForEachRootClient(delegate(IClientAPI client)
463 {
464 client.SendWindData(windSpeeds);
465 });
466 }
467 }
468 }
469 /// <summary>
470 /// Calculate the sun's orbital position and its velocity.
471 /// </summary>
472  
473 private void GenWindPos()
474 {
475 if (m_activeWindPlugin != null)
476 {
477 // Tell Wind Plugin to update it's wind data
478 m_activeWindPlugin.WindUpdate(m_frame);
479 }
480 }
481 }
482 }