29 using System.Collections.Generic;
30 using System.Reflection;
35 using OpenSim.Framework;
36 using OpenSim.Region.Framework.Interfaces;
37 using OpenSim.Region.Framework.Scenes;
39 namespace OpenSim.
Region.CoreModules
41 [Extension(Path =
"/OpenSim/RegionModules", NodeName =
"RegionModule", Id =
"SunModule")]
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
54 private const double m_SeasonalTilt = 0.03 * Math.PI;
55 private const double m_AverageTilt = -0.25 * Math.PI;
56 private const double m_SunCycle = 2.0D * Math.PI;
57 private const double m_SeasonalCycle = 2.0D * Math.PI;
63 private bool ready =
false;
69 private bool receivedEstateToolsSunUpdate =
false;
72 private int m_UpdateInterval = 0;
75 private double m_DayLengthHours = 0;
78 private int m_YearLengthDays = 0;
82 private double m_HorizonShift = 0;
85 private double m_DayTimeSunHourScale;
90 private int d_frame_mod = 100;
91 private double d_day_length = 4;
92 private int d_year_length = 60;
93 private double d_day_night = 0.5;
94 private double d_DayTimeSunHourScale = 0.5;
101 private uint m_frame = 0;
104 private Scene m_scene = null;
107 private long TicksToEpoch;
108 private uint SecondsPerSunCycle;
109 private uint SecondsPerYear;
110 private double SunSpeed;
111 private double SeasonSpeed;
113 private long TicksUTCOffset = 0;
115 private float OrbitalPosition;
116 private double HorizonShift;
117 private double TotalDistanceTravelled;
118 private double SeasonalOffset;
119 private float Magnitude;
123 private Vector3
Position = Vector3.Zero;
124 private Vector3
Velocity = Vector3.Zero;
125 private Quaternion Tilt =
new Quaternion(1.0f, 0.0f, 0.0f, 0.0f);
128 private bool m_SunFixed =
false;
129 private float m_SunFixedHour = 0f;
131 private const int TICKS_PER_SECOND = 10000000;
133 private ulong m_CurrentTimeOffset = 0;
136 private ulong CurrentTime
140 ulong ctime = (ulong)(((DateTime.Now.Ticks) - TicksToEpoch + TicksUTCOffset) / TICKS_PER_SECOND);
141 return ctime + m_CurrentTimeOffset;
151 private void GenSunPos()
154 PosTime = CurrentTime;
167 PosTime = CurrentTime / SecondsPerSunCycle;
170 PosTime *= SecondsPerSunCycle;
174 PosTime += (ulong)((m_SunFixedHour / 24.0) * (ulong)SecondsPerSunCycle);
178 if (m_DayTimeSunHourScale != 0.5f)
180 ulong CurDaySeconds = CurrentTime % SecondsPerSunCycle;
181 double CurDayPercentage = (double)CurDaySeconds / SecondsPerSunCycle;
183 ulong DayLightSeconds = (ulong)(m_DayTimeSunHourScale * SecondsPerSunCycle);
184 ulong NightSeconds = SecondsPerSunCycle - DayLightSeconds;
186 PosTime = CurrentTime / SecondsPerSunCycle;
187 PosTime *= SecondsPerSunCycle;
189 if (CurDayPercentage < 0.5)
191 PosTime += (ulong)((CurDayPercentage / .5) * DayLightSeconds);
195 PosTime += DayLightSeconds;
196 PosTime += (ulong)(((CurDayPercentage - 0.5) / .5) * NightSeconds);
201 TotalDistanceTravelled = SunSpeed * PosTime;
203 OrbitalPosition = (float)(TotalDistanceTravelled % m_SunCycle);
208 SeasonalOffset = SeasonSpeed * PosTime;
209 Tilt.W = (float)(m_AverageTilt + (m_SeasonalTilt * Math.Sin(SeasonalOffset)));
216 Position.X = (float)Math.Cos(-TotalDistanceTravelled);
217 Position.Y = (float)Math.Sin(-TotalDistanceTravelled);
230 Position.Z = Position.Z + (float)HorizonShift;
231 Position = Vector3.Normalize(Position);
237 Velocity.Z = (float)SunSpeed;
241 Magnitude = Position.Length();
256 if (receivedEstateToolsSunUpdate)
258 m_scene.RegionInfo.RegionSettings.SunVector = Position;
262 private float GetCurrentTimeAsLindenSunHour()
264 float curtime = m_SunFixed ? m_SunFixedHour : GetCurrentSunHour();
265 return (curtime + 6.0f) % 24.0f;
268 #region INonSharedRegion Methods
279 TimeZone local = TimeZone.CurrentTimeZone;
280 TicksUTCOffset = local.GetUtcOffset(local.ToLocalTime(DateTime.Now)).Ticks;
281 m_log.DebugFormat(
"[SUN]: localtime offset is {0}", TicksUTCOffset);
285 TicksToEpoch =
new DateTime(1970, 1, 1).Ticks;
295 m_YearLengthDays = config.Configs[
"Sun"].GetInt(
"year_length", d_year_length);
297 m_DayLengthHours = config.Configs[
"Sun"].GetDouble(
"day_length", d_day_length);
301 m_HorizonShift = config.Configs[
"Sun"].GetDouble(
"day_night_offset", d_day_night);
304 m_DayTimeSunHourScale = config.Configs[
"Sun"].GetDouble(
"day_time_sun_hour_scale", d_DayTimeSunHourScale);
307 m_UpdateInterval = config.Configs[
"Sun"].GetInt(
"update_interval", d_frame_mod);
311 m_log.Debug(
"[SUN]: Configuration access failed, using defaults. Reason: " + e.Message);
312 m_YearLengthDays = d_year_length;
313 m_DayLengthHours = d_day_length;
314 m_HorizonShift = d_day_night;
315 m_UpdateInterval = d_frame_mod;
316 m_DayTimeSunHourScale = d_DayTimeSunHourScale;
322 SecondsPerSunCycle = (uint) (m_DayLengthHours * 60 * 60);
323 SecondsPerYear = (uint) (SecondsPerSunCycle*m_YearLengthDays);
332 SunSpeed = m_SunCycle/SecondsPerSunCycle;
333 SeasonSpeed = m_SeasonalCycle/SecondsPerYear;
337 HorizonShift = m_HorizonShift;
340 m_log.Debug(
"[SUN]: Initialization completed. Day is " + SecondsPerSunCycle +
" seconds, and year is " + m_YearLengthDays +
" days");
341 m_log.Debug(
"[SUN]: Axis offset is " + m_HorizonShift);
342 m_log.Debug(
"[SUN]: Percentage of time for daylight " + m_DayTimeSunHourScale);
343 m_log.Debug(
"[SUN]: Positional data updated every " + m_UpdateInterval +
" frames");
346 public Type ReplaceableInterface
356 scene.EventManager.OnFrame += SunUpdate;
357 scene.EventManager.OnAvatarEnteringNewParcel += AvatarEnteringParcel;
358 scene.EventManager.OnEstateToolsSunUpdate += EstateToolsSunUpdate;
359 scene.EventManager.OnGetCurrentTimeAsLindenSunHour += GetCurrentTimeAsLindenSunHour;
361 scene.RegisterModuleInterface<
ISunModule>(
this);
365 foreach (KeyValuePair<string, string> kvp
in GetParamList())
367 string sunCommand = string.Format(
"sun {0}", kvp.Key);
368 m_scene.AddCommand(
"Regions",
this, sunCommand, string.Format(
"{0} [<value>]", sunCommand), kvp.Value,
"", HandleSunConsoleCommand);
370 m_scene.AddCommand(
"Regions",
this,
"sun help",
"sun help",
"list parameters that can be changed",
"", HandleSunConsoleCommand);
371 m_scene.AddCommand(
"Regions",
this,
"sun list",
"sun list",
"list parameters that can be changed",
"", HandleSunConsoleCommand);
380 m_scene.EventManager.OnFrame -= SunUpdate;
381 m_scene.EventManager.OnAvatarEnteringNewParcel -= AvatarEnteringParcel;
382 m_scene.EventManager.OnEstateToolsSunUpdate -= EstateToolsSunUpdate;
383 m_scene.EventManager.OnGetCurrentTimeAsLindenSunHour -= GetCurrentTimeAsLindenSunHour;
396 get {
return "SunModule"; }
401 #region EventManager Events
411 client.SendSunPos(
Position,
Velocity, PosTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
417 client.SendSunPos(
Position,
Velocity, CurrentTime, SecondsPerSunCycle, SecondsPerYear, OrbitalPosition);
424 if (((m_frame++ % m_UpdateInterval) != 0) || !ready || m_SunFixed || !receivedEstateToolsSunUpdate)
429 SunUpdateToAllClients();
438 private void AvatarEnteringParcel(
ScenePresence avatar,
int localLandID, UUID regionID)
445 if (m_scene.RegionInfo.RegionHandle == regionHandle)
450 if (m_scene.RegionInfo.RegionSettings.UseEstateSun)
452 sunFixedHour = (float)m_scene.RegionInfo.EstateSettings.SunPosition;
453 fixedSun = m_scene.RegionInfo.EstateSettings.FixedSun;
457 sunFixedHour = (float)m_scene.RegionInfo.RegionSettings.SunPosition - 6.0f;
458 fixedSun = m_scene.RegionInfo.RegionSettings.FixedSun;
462 while (sunFixedHour > 24.0f)
465 while (sunFixedHour < 0)
468 m_SunFixedHour = sunFixedHour;
469 m_SunFixed = fixedSun;
474 receivedEstateToolsSunUpdate =
true;
480 SunUpdateToAllClients();
488 private void SunUpdateToAllClients()
490 m_scene.ForEachRootClient(delegate(
IClientAPI client)
496 #region ISunModule Members
500 switch (param.ToLower())
503 return m_YearLengthDays;
506 return m_DayLengthHours;
508 case "day_night_offset":
509 return m_HorizonShift;
511 case "day_time_sun_hour_scale":
512 return m_DayTimeSunHourScale;
514 case "update_interval":
515 return m_UpdateInterval;
518 return GetCurrentTimeAsLindenSunHour();
521 throw new Exception(
"Unknown sun parameter.");
530 m_YearLengthDays = (int)value;
531 SecondsPerYear = (uint) (SecondsPerSunCycle*m_YearLengthDays);
532 SeasonSpeed = m_SeasonalCycle/SecondsPerYear;
536 m_DayLengthHours = value;
537 SecondsPerSunCycle = (uint) (m_DayLengthHours * 60 * 60);
538 SecondsPerYear = (uint) (SecondsPerSunCycle*m_YearLengthDays);
539 SunSpeed = m_SunCycle/SecondsPerSunCycle;
540 SeasonSpeed = m_SeasonalCycle/SecondsPerYear;
543 case "day_night_offset":
544 m_HorizonShift = value;
545 HorizonShift = m_HorizonShift;
548 case "day_time_sun_hour_scale":
549 m_DayTimeSunHourScale = value;
552 case "update_interval":
553 m_UpdateInterval = (int)value;
557 value = (value + 18.0) % 24.0;
559 m_CurrentTimeOffset = 0;
560 m_CurrentTimeOffset = (ulong)(SecondsPerSunCycle * value/ 24.0) - (CurrentTime % SecondsPerSunCycle);
564 throw new Exception(
"Unknown sun parameter.");
571 SunUpdateToAllClients();
576 float ticksleftover = CurrentTime % SecondsPerSunCycle;
578 return (24.0f * (ticksleftover / SecondsPerSunCycle));
585 if (m_scene.ConsoleScene() == null)
590 m_log.InfoFormat(
"[Sun]: Please change to a specific region in order to set Sun parameters.");
594 if (m_scene.ConsoleScene() != m_scene)
596 m_log.InfoFormat(
"[Sun]: Console Scene is not my scene.");
600 m_log.InfoFormat(
"[Sun]: Processing command.");
602 foreach (
string output
in ParseCmdParams(cmdparams))
604 MainConsole.Instance.Output(output);
608 private Dictionary<string, string> GetParamList()
610 Dictionary<string, string> Params =
new Dictionary<string, string>();
612 Params.Add(
"year_length",
"number of days to a year");
613 Params.Add(
"day_length",
"number of hours to a day");
614 Params.Add(
"day_night_offset",
"induces a horizon shift");
615 Params.Add(
"update_interval",
"how often to update the sun's position in frames");
616 Params.Add(
"day_time_sun_hour_scale",
"scales day light vs nite hours to change day/night ratio");
617 Params.Add(
"current_time",
"time in seconds of the simulator");
622 private List<string> ParseCmdParams(
string[] args)
624 List<string> Output =
new List<string>();
626 if ((args.Length == 1) || (args[1].ToLower() ==
"help") || (args[1].ToLower() ==
"list"))
628 Output.Add(
"The following parameters can be changed or viewed:");
629 foreach (KeyValuePair<string, string> kvp
in GetParamList())
631 Output.Add(String.Format(
"{0} - {1}",kvp.Key, kvp.Value));
636 if (args.Length == 2)
640 double value = GetSunParameter(args[1]);
641 Output.Add(String.Format(
"Parameter {0} is {1}.", args[1], value.ToString()));
645 Output.Add(String.Format(
"Unknown parameter {0}.", args[1]));
649 else if (args.Length == 3)
652 if (!
double.TryParse(args[2], out value))
654 Output.Add(String.Format(
"The parameter value {0} is not a valid number.", args[2]));
658 SetSunParameter(args[1].ToLower(), value);
659 Output.Add(String.Format(
"Parameter {0} set to {1}.", args[1], value.ToString()));
IClientAPI ControllingClient
void Initialise(IConfigSource config)
This is called to initialize the region module. For shared modules, this is called exactly once...
void SetSunParameter(string param, double value)
void RemoveRegion(Scene scene)
This is called whenever a Scene is removed. For shared modules, this can happen several times...
float GetCurrentSunHour()
void AddRegion(Scene scene)
This is called whenever a Scene is added. For shared modules, this can happen several times...
void Close()
This is the inverse to Initialise. After a Close(), this instance won't be usable anymore...
void HandleSunConsoleCommand(string module, string[] cmdparams)
void SunToClient(IClientAPI client)
double GetSunParameter(string param)
void EstateToolsSunUpdate(ulong regionHandle)
void RegionLoaded(Scene scene)
This will be called once for every scene loaded. In a shared module this will be multiple times in on...