clockwerk-opensim-stable – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | vero | 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 | namespace OpenSim.Region.CoreModules |
||
40 | { |
||
41 | [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SunModule")] |
||
42 | public class SunModule : ISunModule |
||
43 | { |
||
44 | /// <summary> |
||
45 | /// Note: Sun Hour can be a little deceaving. Although it's based on a 24 hour clock |
||
46 | /// it is not based on ~06:00 == Sun Rise. Rather it is based on 00:00 being sun-rise. |
||
47 | /// </summary> |
||
48 | |||
49 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
||
50 | |||
51 | // |
||
52 | // Global Constants used to determine where in the sky the sun is |
||
53 | // |
||
54 | private const double m_SeasonalTilt = 0.03 * Math.PI; // A daily shift of approximately 1.7188 degrees |
||
55 | private const double m_AverageTilt = -0.25 * Math.PI; // A 45 degree tilt |
||
56 | private const double m_SunCycle = 2.0D * Math.PI; // A perfect circle measured in radians |
||
57 | private const double m_SeasonalCycle = 2.0D * Math.PI; // Ditto |
||
58 | |||
59 | // |
||
60 | // Per Region Values |
||
61 | // |
||
62 | |||
63 | private bool ready = false; |
||
64 | |||
65 | // This solves a chick before the egg problem |
||
66 | // the local SunFixedHour and SunFixed variables MUST be updated |
||
67 | // at least once with the proper Region Settings before we start |
||
68 | // updating those region settings in GenSunPos() |
||
69 | private bool receivedEstateToolsSunUpdate = false; |
||
70 | |||
71 | // Configurable values |
||
72 | private string m_RegionMode = "SL"; |
||
73 | |||
74 | // Sun's position information is updated and sent to clients every m_UpdateInterval frames |
||
75 | private int m_UpdateInterval = 0; |
||
76 | |||
77 | // Number of real time hours per virtual day |
||
78 | private double m_DayLengthHours = 0; |
||
79 | |||
80 | // Number of virtual days to a virtual year |
||
81 | private int m_YearLengthDays = 0; |
||
82 | |||
83 | // Ratio of Daylight hours to Night time hours. This is accomplished by shifting the |
||
84 | // sun's orbit above the horizon |
||
85 | private double m_HorizonShift = 0; |
||
86 | |||
87 | // Used to scale current and positional time to adjust length of an hour during day vs night. |
||
88 | private double m_DayTimeSunHourScale; |
||
89 | |||
90 | // private double m_longitude = 0; |
||
91 | // private double m_latitude = 0; |
||
92 | // Configurable defaults Defaults close to SL |
||
93 | private string d_mode = "SL"; |
||
94 | private int d_frame_mod = 100; // Every 10 seconds (actually less) |
||
95 | private double d_day_length = 4; // A VW day is 4 RW hours long |
||
96 | private int d_year_length = 60; // There are 60 VW days in a VW year |
||
97 | private double d_day_night = 0.5; // axis offset: Default Hoizon shift to try and closely match the sun model in LL Viewer |
||
98 | private double d_DayTimeSunHourScale = 0.5; // Day/Night hours are equal |
||
99 | |||
100 | |||
101 | // private double d_longitude = -73.53; |
||
102 | // private double d_latitude = 41.29; |
||
103 | |||
104 | // Frame counter |
||
105 | private uint m_frame = 0; |
||
106 | |||
107 | // Cached Scene reference |
||
108 | private Scene m_scene = null; |
||
109 | |||
110 | // Calculated Once in the lifetime of a region |
||
111 | private long TicksToEpoch; // Elapsed time for 1/1/1970 |
||
112 | private uint SecondsPerSunCycle; // Length of a virtual day in RW seconds |
||
113 | private uint SecondsPerYear; // Length of a virtual year in RW seconds |
||
114 | private double SunSpeed; // Rate of passage in radians/second |
||
115 | private double SeasonSpeed; // Rate of change for seasonal effects |
||
116 | // private double HoursToRadians; // Rate of change for seasonal effects |
||
117 | private long TicksUTCOffset = 0; // seconds offset from UTC |
||
118 | // Calculated every update |
||
119 | private float OrbitalPosition; // Orbital placement at a point in time |
||
120 | private double HorizonShift; // Axis offset to skew day and night |
||
121 | private double TotalDistanceTravelled; // Distance since beginning of time (in radians) |
||
122 | private double SeasonalOffset; // Seaonal variation of tilt |
||
123 | private float Magnitude; // Normal tilt |
||
124 | // private double VWTimeRatio; // VW time as a ratio of real time |
||
125 | |||
126 | // Working values |
||
127 | private Vector3 Position = Vector3.Zero; |
||
128 | private Vector3 Velocity = Vector3.Zero; |
||
129 | private Quaternion Tilt = new Quaternion(1.0f, 0.0f, 0.0f, 0.0f); |
||
130 | |||
131 | // Used to fix the sun in the sky so it doesn't move based on current time |
||
132 | private bool m_SunFixed = false; |
||
133 | private float m_SunFixedHour = 0f; |
||
134 | |||
135 | private const int TICKS_PER_SECOND = 10000000; |
||
136 | |||
137 | // Current time in elapsed seconds since Jan 1st 1970 |
||
138 | private ulong CurrentTime |
||
139 | { |
||
140 | get |
||
141 | { |
||
142 | return (ulong)(((DateTime.Now.Ticks) - TicksToEpoch + TicksUTCOffset) / TICKS_PER_SECOND); |
||
143 | } |
||
144 | } |
||
145 | |||
146 | // Time in seconds since UTC to use to calculate sun position. |
||
147 | ulong PosTime = 0; |
||
148 | |||
149 | /// <summary> |
||
150 | /// Calculate the sun's orbital position and its velocity. |
||
151 | /// </summary> |
||
152 | private void GenSunPos() |
||
153 | { |
||
154 | // Time in seconds since UTC to use to calculate sun position. |
||
155 | PosTime = CurrentTime; |
||
156 | |||
157 | if (m_SunFixed) |
||
158 | { |
||
159 | // SunFixedHour represents the "hour of day" we would like |
||
160 | // It's represented in 24hr time, with 0 hour being sun-rise |
||
161 | // Because our day length is probably not 24hrs {LL is 6} we need to do a bit of math |
||
162 | |||
163 | // Determine the current "day" from current time, so we can use "today" |
||
164 | // to determine Seasonal Tilt and what'not |
||
165 | |||
166 | // Integer math rounded is on purpose to drop fractional day, determines number |
||
167 | // of virtual days since Epoch |
||
168 | PosTime = CurrentTime / SecondsPerSunCycle; |
||
169 | |||
170 | // Since we want number of seconds since Epoch, multiply back up |
||
171 | PosTime *= SecondsPerSunCycle; |
||
172 | |||
173 | // Then offset by the current Fixed Sun Hour |
||
174 | // Fixed Sun Hour needs to be scaled to reflect the user configured Seconds Per Sun Cycle |
||
175 | PosTime += (ulong)((m_SunFixedHour / 24.0) * (ulong)SecondsPerSunCycle); |
||
176 | } |
||
177 | else |
||
178 | { |
||
179 | if (m_DayTimeSunHourScale != 0.5f) |
||
180 | { |
||
181 | ulong CurDaySeconds = CurrentTime % SecondsPerSunCycle; |
||
182 | double CurDayPercentage = (double)CurDaySeconds / SecondsPerSunCycle; |
||
183 | |||
184 | ulong DayLightSeconds = (ulong)(m_DayTimeSunHourScale * SecondsPerSunCycle); |
||
185 | ulong NightSeconds = SecondsPerSunCycle - DayLightSeconds; |
||
186 | |||
187 | PosTime = CurrentTime / SecondsPerSunCycle; |
||
188 | PosTime *= SecondsPerSunCycle; |
||
189 | |||
190 | if (CurDayPercentage < 0.5) |
||
191 | { |
||
192 | PosTime += (ulong)((CurDayPercentage / .5) * DayLightSeconds); |
||
193 | } |
||
194 | else |
||
195 | { |
||
196 | PosTime += DayLightSeconds; |
||
197 | PosTime += (ulong)(((CurDayPercentage - 0.5) / .5) * NightSeconds); |
||
198 | } |
||
199 | } |
||
200 | } |
||
201 | |||
202 | TotalDistanceTravelled = SunSpeed * PosTime; // distance measured in radians |
||
203 | |||
204 | OrbitalPosition = (float)(TotalDistanceTravelled % m_SunCycle); // position measured in radians |
||
205 | |||
206 | // TotalDistanceTravelled += HoursToRadians-(0.25*Math.PI)*Math.Cos(HoursToRadians)-OrbitalPosition; |
||
207 | // OrbitalPosition = (float) (TotalDistanceTravelled%SunCycle); |
||
208 | |||
209 | SeasonalOffset = SeasonSpeed * PosTime; // Present season determined as total radians travelled around season cycle |
||
210 | Tilt.W = (float)(m_AverageTilt + (m_SeasonalTilt * Math.Sin(SeasonalOffset))); // Calculate seasonal orbital N/S tilt |
||
211 | |||
212 | // m_log.Debug("[SUN] Total distance travelled = "+TotalDistanceTravelled+", present position = "+OrbitalPosition+"."); |
||
213 | // m_log.Debug("[SUN] Total seasonal progress = "+SeasonalOffset+", present tilt = "+Tilt.W+"."); |
||
214 | |||
215 | // The sun rotates about the Z axis |
||
216 | |||
217 | Position.X = (float)Math.Cos(-TotalDistanceTravelled); |
||
218 | Position.Y = (float)Math.Sin(-TotalDistanceTravelled); |
||
219 | Position.Z = 0; |
||
220 | |||
221 | // For interest we rotate it slightly about the X access. |
||
222 | // Celestial tilt is a value that ranges .025 |
||
223 | |||
224 | Position *= Tilt; |
||
225 | |||
226 | // Finally we shift the axis so that more of the |
||
227 | // circle is above the horizon than below. This |
||
228 | // makes the nights shorter than the days. |
||
229 | |||
230 | Position = Vector3.Normalize(Position); |
||
231 | Position.Z = Position.Z + (float)HorizonShift; |
||
232 | Position = Vector3.Normalize(Position); |
||
233 | |||
234 | // m_log.Debug("[SUN] Position("+Position.X+","+Position.Y+","+Position.Z+")"); |
||
235 | |||
236 | Velocity.X = 0; |
||
237 | Velocity.Y = 0; |
||
238 | Velocity.Z = (float)SunSpeed; |
||
239 | |||
240 | // Correct angular velocity to reflect the seasonal rotation |
||
241 | |||
242 | Magnitude = Position.Length(); |
||
243 | if (m_SunFixed) |
||
244 | { |
||
245 | Velocity.X = 0; |
||
246 | Velocity.Y = 0; |
||
247 | Velocity.Z = 0; |
||
248 | } |
||
249 | else |
||
250 | { |
||
251 | Velocity = (Velocity * Tilt) * (1.0f / Magnitude); |
||
252 | } |
||
253 | |||
254 | // TODO: Decouple this, so we can get rid of Linden Hour info |
||
255 | // Update Region with new Sun Vector |
||
256 | // set estate settings for region access to sun position |
||
257 | if (receivedEstateToolsSunUpdate) |
||
258 | { |
||
259 | m_scene.RegionInfo.RegionSettings.SunVector = Position; |
||
260 | } |
||
261 | } |
||
262 | |||
263 | private float GetCurrentTimeAsLindenSunHour() |
||
264 | { |
||
265 | if (m_SunFixed) |
||
266 | return m_SunFixedHour + 6; |
||
267 | |||
268 | return GetCurrentSunHour() + 6.0f; |
||
269 | } |
||
270 | |||
271 | #region INonSharedRegion Methods |
||
272 | |||
273 | // Called immediately after the module is loaded for a given region |
||
274 | // i.e. Immediately after instance creation. |
||
275 | public void Initialise(IConfigSource config) |
||
276 | { |
||
277 | m_frame = 0; |
||
278 | |||
279 | // This one puts an entry in the main help screen |
||
280 | // m_scene.AddCommand("Regions", this, "sun", "sun", "Usage: sun [param] [value] - Get or Update Sun module paramater", null); |
||
281 | |||
282 | TimeZone local = TimeZone.CurrentTimeZone; |
||
283 | TicksUTCOffset = local.GetUtcOffset(local.ToLocalTime(DateTime.Now)).Ticks; |
||
284 | m_log.DebugFormat("[SUN]: localtime offset is {0}", TicksUTCOffset); |
||
285 | |||
286 | // Align ticks with Second Life |
||
287 | |||
288 | TicksToEpoch = new DateTime(1970, 1, 1).Ticks; |
||
289 | |||
290 | // Just in case they don't have the stanzas |
||
291 | try |
||
292 | { |
||
293 | // Mode: determines how the sun is handled |
||
294 | m_RegionMode = config.Configs["Sun"].GetString("mode", d_mode); |
||
295 | // Mode: determines how the sun is handled |
||
296 | // m_latitude = config.Configs["Sun"].GetDouble("latitude", d_latitude); |
||
297 | // Mode: determines how the sun is handled |
||
298 | // m_longitude = config.Configs["Sun"].GetDouble("longitude", d_longitude); |
||
299 | // Year length in days |
||
300 | m_YearLengthDays = config.Configs["Sun"].GetInt("year_length", d_year_length); |
||
301 | // Day length in decimal hours |
||
302 | m_DayLengthHours = config.Configs["Sun"].GetDouble("day_length", d_day_length); |
||
303 | |||
304 | // Horizon shift, this is used to shift the sun's orbit, this affects the day / night ratio |
||
305 | // must hard code to ~.5 to match sun position in LL based viewers |
||
306 | m_HorizonShift = config.Configs["Sun"].GetDouble("day_night_offset", d_day_night); |
||
307 | |||
308 | // Scales the sun hours 0...12 vs 12...24, essentially makes daylight hours longer/shorter vs nighttime hours |
||
309 | m_DayTimeSunHourScale = config.Configs["Sun"].GetDouble("day_time_sun_hour_scale", d_DayTimeSunHourScale); |
||
310 | |||
311 | // Update frequency in frames |
||
312 | m_UpdateInterval = config.Configs["Sun"].GetInt("update_interval", d_frame_mod); |
||
313 | } |
||
314 | catch (Exception e) |
||
315 | { |
||
316 | m_log.Debug("[SUN]: Configuration access failed, using defaults. Reason: " + e.Message); |
||
317 | m_RegionMode = d_mode; |
||
318 | m_YearLengthDays = d_year_length; |
||
319 | m_DayLengthHours = d_day_length; |
||
320 | m_HorizonShift = d_day_night; |
||
321 | m_UpdateInterval = d_frame_mod; |
||
322 | m_DayTimeSunHourScale = d_DayTimeSunHourScale; |
||
323 | |||
324 | // m_latitude = d_latitude; |
||
325 | // m_longitude = d_longitude; |
||
326 | } |
||
327 | |||
328 | switch (m_RegionMode) |
||
329 | { |
||
330 | case "T1": |
||
331 | default: |
||
332 | case "SL": |
||
333 | // Time taken to complete a cycle (day and season) |
||
334 | |||
335 | SecondsPerSunCycle = (uint) (m_DayLengthHours * 60 * 60); |
||
336 | SecondsPerYear = (uint) (SecondsPerSunCycle*m_YearLengthDays); |
||
337 | |||
338 | // Ration of real-to-virtual time |
||
339 | |||
340 | // VWTimeRatio = 24/m_day_length; |
||
341 | |||
342 | // Speed of rotation needed to complete a cycle in the |
||
343 | // designated period (day and season) |
||
344 | |||
345 | SunSpeed = m_SunCycle/SecondsPerSunCycle; |
||
346 | SeasonSpeed = m_SeasonalCycle/SecondsPerYear; |
||
347 | |||
348 | // Horizon translation |
||
349 | |||
350 | HorizonShift = m_HorizonShift; // Z axis translation |
||
351 | // HoursToRadians = (SunCycle/24)*VWTimeRatio; |
||
352 | |||
353 | m_log.Debug("[SUN]: Mode is " + m_RegionMode); |
||
354 | m_log.Debug("[SUN]: Initialization completed. Day is " + SecondsPerSunCycle + " seconds, and year is " + m_YearLengthDays + " days"); |
||
355 | m_log.Debug("[SUN]: Axis offset is " + m_HorizonShift); |
||
356 | m_log.Debug("[SUN]: Percentage of time for daylight " + m_DayTimeSunHourScale); |
||
357 | m_log.Debug("[SUN]: Positional data updated every " + m_UpdateInterval + " frames"); |
||
358 | |||
359 | break; |
||
360 | } |
||
361 | |||
362 | } |
||
363 | |||
364 | public Type ReplaceableInterface |
||
365 | { |
||
366 | get { return null; } |
||
367 | } |
||
368 | |||
369 | public void AddRegion(Scene scene) |
||
370 | { |
||
371 | m_scene = scene; |
||
372 | // Insert our event handling hooks |
||
373 | |||
374 | scene.EventManager.OnFrame += SunUpdate; |
||
375 | scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel; |
||
376 | scene.EventManager.OnEstateToolsSunUpdate += EstateToolsSunUpdate; |
||
377 | scene.EventManager.OnGetCurrentTimeAsLindenSunHour += GetCurrentTimeAsLindenSunHour; |
||
378 | |||
379 | scene.RegisterModuleInterface<ISunModule>(this); |
||
380 | |||
381 | // This one enables the ability to type just "sun" without any parameters |
||
382 | // m_scene.AddCommand("Regions", this, "sun", "", "", HandleSunConsoleCommand); |
||
383 | foreach (KeyValuePair<string, string> kvp in GetParamList()) |
||
384 | { |
||
385 | string sunCommand = string.Format("sun {0}", kvp.Key); |
||
386 | m_scene.AddCommand("Regions", this, sunCommand, string.Format("{0} [<value>]", sunCommand), kvp.Value, "", HandleSunConsoleCommand); |
||
387 | } |
||
388 | |||
389 | ready = true; |
||
390 | } |
||
391 | |||
392 | public void RemoveRegion(Scene scene) |
||
393 | { |
||
394 | ready = false; |
||
395 | |||
396 | // Remove our hooks |
||
397 | m_scene.EventManager.OnFrame -= SunUpdate; |
||
398 | m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel; |
||
399 | m_scene.EventManager.OnEstateToolsSunUpdate -= EstateToolsSunUpdate; |
||
400 | m_scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour; |
||
401 | } |
||
402 | |||
403 | public void RegionLoaded(Scene scene) |
||
404 | { |
||
405 | } |
||
406 | |||
407 | public void Close() |
||
408 | { |
||
409 | } |
||
410 | |||
411 | public string Name |
||
412 | { |
||
413 | get { return "SunModule"; } |
||
414 | } |
||
415 | |||
416 | #endregion |
||
417 | |||
418 | #region EventManager Events |
||
419 | |||
420 | public void SunToClient(IClientAPI client) |
||
421 | { |
||
422 | if (m_RegionMode != "T1") |
||
423 | { |
||
424 | if (ready) |
||
425 | { |
||
426 | if (m_SunFixed) |
||
427 | { |
||
428 | // m_log.DebugFormat("[SUN]: SunHour {0}, Position {1}, PosTime {2}, OrbitalPosition : {3} ", m_SunFixedHour, Position.ToString(), PosTime.ToString(), OrbitalPosition.ToString()); |
||
429 | client.SendSunPos(Position, Velocity, PosTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); |
||
430 | } |
||
431 | else |
||
432 | { |
||
433 | // m_log.DebugFormat("[SUN]: SunHour {0}, Position {1}, PosTime {2}, OrbitalPosition : {3} ", m_SunFixedHour, Position.ToString(), PosTime.ToString(), OrbitalPosition.ToString()); |
||
434 | client.SendSunPos(Position, Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition); |
||
435 | } |
||
436 | } |
||
437 | } |
||
438 | } |
||
439 | |||
440 | public void SunUpdate() |
||
441 | { |
||
442 | if (((m_frame++ % m_UpdateInterval) != 0) || !ready || m_SunFixed || !receivedEstateToolsSunUpdate) |
||
443 | return; |
||
444 | |||
445 | GenSunPos(); // Generate shared values once |
||
446 | |||
447 | SunUpdateToAllClients(); |
||
448 | } |
||
449 | |||
450 | /// <summary> |
||
451 | /// When an avatar enters the region, it's probably a good idea to send them the current sun info |
||
452 | /// </summary> |
||
453 | /// <param name="avatar"></param> |
||
454 | /// <param name="localLandID"></param> |
||
455 | /// <param name="regionID"></param> |
||
456 | private void AvatarEnteringParcel(ScenePresence avatar, int localLandID, UUID regionID) |
||
457 | { |
||
458 | SunToClient(avatar.ControllingClient); |
||
459 | } |
||
460 | |||
461 | public void EstateToolsSunUpdate(ulong regionHandle) |
||
462 | { |
||
463 | if (m_scene.RegionInfo.RegionHandle == regionHandle) |
||
464 | { |
||
465 | float sunFixedHour; |
||
466 | bool fixedSun; |
||
467 | |||
468 | if (m_scene.RegionInfo.RegionSettings.UseEstateSun) |
||
469 | { |
||
470 | sunFixedHour = (float)m_scene.RegionInfo.EstateSettings.SunPosition; |
||
471 | fixedSun = m_scene.RegionInfo.EstateSettings.FixedSun; |
||
472 | } |
||
473 | else |
||
474 | { |
||
475 | sunFixedHour = (float)m_scene.RegionInfo.RegionSettings.SunPosition - 6.0f; |
||
476 | fixedSun = m_scene.RegionInfo.RegionSettings.FixedSun; |
||
477 | } |
||
478 | |||
479 | // Must limit the Sun Hour to 0 ... 24 |
||
480 | while (sunFixedHour > 24.0f) |
||
481 | sunFixedHour -= 24; |
||
482 | |||
483 | while (sunFixedHour < 0) |
||
484 | sunFixedHour += 24; |
||
485 | |||
486 | m_SunFixedHour = sunFixedHour; |
||
487 | m_SunFixed = fixedSun; |
||
488 | |||
489 | // m_log.DebugFormat("[SUN]: Sun Settings Update: Fixed Sun? : {0}", m_SunFixed.ToString()); |
||
490 | // m_log.DebugFormat("[SUN]: Sun Settings Update: Sun Hour : {0}", m_SunFixedHour.ToString()); |
||
491 | |||
492 | receivedEstateToolsSunUpdate = true; |
||
493 | |||
494 | // Generate shared values |
||
495 | GenSunPos(); |
||
496 | |||
497 | // When sun settings are updated, we should update all clients with new settings. |
||
498 | SunUpdateToAllClients(); |
||
499 | |||
500 | // m_log.DebugFormat("[SUN]: PosTime : {0}", PosTime.ToString()); |
||
501 | } |
||
502 | } |
||
503 | |||
504 | #endregion |
||
505 | |||
506 | private void SunUpdateToAllClients() |
||
507 | { |
||
508 | m_scene.ForEachRootClient(delegate(IClientAPI client) |
||
509 | { |
||
510 | SunToClient(client); |
||
511 | }); |
||
512 | } |
||
513 | |||
514 | #region ISunModule Members |
||
515 | |||
516 | public double GetSunParameter(string param) |
||
517 | { |
||
518 | switch (param.ToLower()) |
||
519 | { |
||
520 | case "year_length": |
||
521 | return m_YearLengthDays; |
||
522 | |||
523 | case "day_length": |
||
524 | return m_DayLengthHours; |
||
525 | |||
526 | case "day_night_offset": |
||
527 | return m_HorizonShift; |
||
528 | |||
529 | case "day_time_sun_hour_scale": |
||
530 | return m_DayTimeSunHourScale; |
||
531 | |||
532 | case "update_interval": |
||
533 | return m_UpdateInterval; |
||
534 | |||
535 | default: |
||
536 | throw new Exception("Unknown sun parameter."); |
||
537 | } |
||
538 | } |
||
539 | |||
540 | public void SetSunParameter(string param, double value) |
||
541 | { |
||
542 | HandleSunConsoleCommand("sun", new string[] {param, value.ToString() }); |
||
543 | } |
||
544 | |||
545 | public float GetCurrentSunHour() |
||
546 | { |
||
547 | float ticksleftover = CurrentTime % SecondsPerSunCycle; |
||
548 | |||
549 | return (24.0f * (ticksleftover / SecondsPerSunCycle)); |
||
550 | } |
||
551 | |||
552 | #endregion |
||
553 | |||
554 | public void HandleSunConsoleCommand(string module, string[] cmdparams) |
||
555 | { |
||
556 | if (m_scene.ConsoleScene() == null) |
||
557 | { |
||
558 | // FIXME: If console region is root then this will be printed by every module. Currently, there is no |
||
559 | // way to prevent this, short of making the entire module shared (which is complete overkill). |
||
560 | // One possibility is to return a bool to signal whether the module has completely handled the command |
||
561 | m_log.InfoFormat("[Sun]: Please change to a specific region in order to set Sun parameters."); |
||
562 | return; |
||
563 | } |
||
564 | |||
565 | if (m_scene.ConsoleScene() != m_scene) |
||
566 | { |
||
567 | m_log.InfoFormat("[Sun]: Console Scene is not my scene."); |
||
568 | return; |
||
569 | } |
||
570 | |||
571 | m_log.InfoFormat("[Sun]: Processing command."); |
||
572 | |||
573 | foreach (string output in ParseCmdParams(cmdparams)) |
||
574 | { |
||
575 | m_log.Info("[SUN] " + output); |
||
576 | } |
||
577 | } |
||
578 | |||
579 | private Dictionary<string, string> GetParamList() |
||
580 | { |
||
581 | Dictionary<string, string> Params = new Dictionary<string, string>(); |
||
582 | |||
583 | Params.Add("year_length", "number of days to a year"); |
||
584 | Params.Add("day_length", "number of seconds to a day"); |
||
585 | Params.Add("day_night_offset", "induces a horizon shift"); |
||
586 | Params.Add("update_interval", "how often to update the sun's position in frames"); |
||
587 | Params.Add("day_time_sun_hour_scale", "scales day light vs nite hours to change day/night ratio"); |
||
588 | |||
589 | return Params; |
||
590 | } |
||
591 | |||
592 | private List<string> ParseCmdParams(string[] args) |
||
593 | { |
||
594 | List<string> Output = new List<string>(); |
||
595 | |||
596 | if ((args.Length == 1) || (args[1].ToLower() == "help") || (args[1].ToLower() == "list")) |
||
597 | { |
||
598 | Output.Add("The following parameters can be changed or viewed:"); |
||
599 | foreach (KeyValuePair<string, string> kvp in GetParamList()) |
||
600 | { |
||
601 | Output.Add(String.Format("{0} - {1}",kvp.Key, kvp.Value)); |
||
602 | } |
||
603 | return Output; |
||
604 | } |
||
605 | |||
606 | if (args.Length == 2) |
||
607 | { |
||
608 | try |
||
609 | { |
||
610 | double value = GetSunParameter(args[1]); |
||
611 | Output.Add(String.Format("Parameter {0} is {1}.", args[1], value.ToString())); |
||
612 | } |
||
613 | catch (Exception) |
||
614 | { |
||
615 | Output.Add(String.Format("Unknown parameter {0}.", args[1])); |
||
616 | } |
||
617 | |||
618 | } |
||
619 | else if (args.Length == 3) |
||
620 | { |
||
621 | float value = 0.0f; |
||
622 | if (!float.TryParse(args[2], out value)) |
||
623 | { |
||
624 | Output.Add(String.Format("The parameter value {0} is not a valid number.", args[2])); |
||
625 | } |
||
626 | |||
627 | switch (args[1].ToLower()) |
||
628 | { |
||
629 | case "year_length": |
||
630 | m_YearLengthDays = (int)value; |
||
631 | break; |
||
632 | |||
633 | case "day_length": |
||
634 | m_DayLengthHours = value; |
||
635 | break; |
||
636 | |||
637 | case "day_night_offset": |
||
638 | m_HorizonShift = value; |
||
639 | break; |
||
640 | |||
641 | case "day_time_sun_hour_scale": |
||
642 | m_DayTimeSunHourScale = value; |
||
643 | break; |
||
644 | |||
645 | case "update_interval": |
||
646 | m_UpdateInterval = (int)value; |
||
647 | break; |
||
648 | |||
649 | default: |
||
650 | Output.Add(String.Format("Unknown parameter {0}.", args[1])); |
||
651 | return Output; |
||
652 | } |
||
653 | |||
654 | Output.Add(String.Format("Parameter {0} set to {1}.", args[1], value.ToString())); |
||
655 | |||
656 | // Generate shared values |
||
657 | GenSunPos(); |
||
658 | |||
659 | // When sun settings are updated, we should update all clients with new settings. |
||
660 | SunUpdateToAllClients(); |
||
661 | } |
||
662 | |||
663 | return Output; |
||
664 | } |
||
665 | } |
||
666 | } |