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