diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/CoreModules/World/Wind/WindModule.cs | 410 |
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 | ||
28 | using System; | 28 | using System; |
29 | using System.Collections.Generic; | 29 | using System.Collections.Generic; |
30 | using System.Reflection; | ||
31 | using log4net; | ||
32 | using Mono.Addins; | ||
30 | using Nini.Config; | 33 | using Nini.Config; |
31 | using OpenMetaverse; | 34 | using OpenMetaverse; |
32 | using OpenSim.Framework; | 35 | using OpenSim.Framework; |
33 | using OpenSim.Region.Framework.Interfaces; | 36 | using OpenSim.Region.Framework.Interfaces; |
34 | using OpenSim.Region.Framework.Scenes; | 37 | using OpenSim.Region.Framework.Scenes; |
35 | 38 | ||
39 | using OpenSim.Region.CoreModules.World.Wind; | ||
40 | |||
36 | namespace OpenSim.Region.CoreModules | 41 | namespace 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 | } |