Skip to content

Commit

Permalink
Merge pull request #38 from baughj/SERVER-172
Browse files Browse the repository at this point in the history
[SERVER-172] Implement support for Aisling time
  • Loading branch information
baughj committed May 30, 2016
2 parents 18ca1e3 + 98f5e64 commit c25c26f
Show file tree
Hide file tree
Showing 6 changed files with 371 additions and 6 deletions.
11 changes: 8 additions & 3 deletions hybrasyl/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
* Kyle Speck <kojasou@hybrasyl.com>
*/

using System.Data.Odbc;
using Hybrasyl.Properties;
using Hybrasyl.XSD;
using log4net;
Expand All @@ -32,7 +31,6 @@
using System.Text;
using System.Threading;
using System.Xml;
using System.Xml.Linq;
using Hybrasyl.XML;
using log4net.Core;
using zlib;
Expand Down Expand Up @@ -73,6 +71,8 @@ public static class Game
private static Thread _loginSendThread;
private static Thread _worldSendThread;

public static DateTime StartDate { get; set; }

private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();

public static void ToggleActive()
Expand Down Expand Up @@ -129,7 +129,7 @@ public static HybrasylConfig GatherConfig()
Config.Network.Login.Port = Convert.ToUInt16(loginPort);

Config.Network.World.Bindaddress = serverIp;
Config.Network.World.Port = Convert.ToUInt16(loginPort);
Config.Network.World.Port = Convert.ToUInt16(worldPort);

Logger.InfoFormat("Using {0}: {1}, {2}, {3}", serverIp, lobbyPort, loginPort, worldPort);

Expand All @@ -154,6 +154,10 @@ public static HybrasylConfig GatherConfig()
Config.Datastore.Username = string.IsNullOrEmpty(redisUser) ? "" : redisUser;
Config.Datastore.Password = string.IsNullOrEmpty(redisPass) ? "" : redisPass;

Config.Time.ServerStart.Value = DateTime.Now.ToString("O");
Config.Time.ServerStart.DefaultAge = "Hybrasyl";
Config.Time.ServerStart.DefaultYear = 1;

return Config;
}

Expand Down Expand Up @@ -293,6 +297,7 @@ public static void Main(string[] args)
World.StartQueueConsumer();

ToggleActive();
StartDate = DateTime.Now;

_lobbyThread = new Thread(new ThreadStart(Lobby.StartListening));
_loginThread = new Thread(new ThreadStart(Login.StartListening));
Expand Down
1 change: 1 addition & 0 deletions hybrasyl/Hybrasyl.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
<ItemGroup>
<Compile Include="Book.cs" />
<Compile Include="Board.cs" />
<Compile Include="Time.cs" />
<Compile Include="Client.cs" />
<Compile Include="Connection.cs" />
<Compile Include="Dialogs.cs" />
Expand Down
10 changes: 8 additions & 2 deletions hybrasyl/Objects/User.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ public class LegendMark
public String Text { get; set; }
public bool Public { get; set; }
public DateTime Created { get; set; }
public int Quantity { get; set; }
/*
public override string ToString()
{
//var ingame = World.TimeConverter.AsString(Created, bool fullTime = false)
}*/
}

[JsonObject]
Expand Down Expand Up @@ -693,13 +699,13 @@ public override void OnClick(User invoker)
profilePacket.WriteString8(Guild.Rank);
profilePacket.WriteString8(Hybrasyl.Constants.REVERSE_CLASSES[(int)Class]);
profilePacket.WriteString8(Guild.Name);
profilePacket.WriteByte((byte)Legend.Count);
profilePacket.WriteByte((byte)Legend.Count );
foreach (var mark in Legend)
{
profilePacket.WriteByte((byte)mark.Icon);
profilePacket.WriteByte((byte)mark.Color);
profilePacket.WriteString8(mark.Prefix);
profilePacket.WriteString8(mark.Text);
profilePacket.WriteString8(mark.ToString());
}
profilePacket.WriteUInt16((ushort)(PortraitData.Length + ProfileText.Length + 4));
profilePacket.WriteUInt16((ushort)PortraitData.Length);
Expand Down
290 changes: 290 additions & 0 deletions hybrasyl/Time.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using log4net;

namespace Hybrasyl
{

public class HybrasylTime
{
public static ILog Logger =
LogManager.GetLogger(
System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

public string Age;
public int Year;
public int Moon;
public int Sun;
public int Hour;
public int Minute;

public const long YearTicks = 12 * MoonTicks;
public const long MoonTicks = 28 * SunTicks;
public const long SunTicks = 24 * HourTicks;
public const long HourTicks = 60 * MinuteTicks;
public const long MinuteTicks = 60 * TimeSpan.TicksPerSecond;

public static readonly List<string> RegexStringList = new List<string>
{
@"(?<Age>[A-Za-z _]*) (?<Year>\d*)(\s*,\s*(?<Moon>\d*)\s*(rd|st|nd|th) moon,\s*(?<Sun>\d*)\s*(rd|st|nd|th) sun,\s*(?<Hour>\d{0,2}):(?<Minute>\d{0,2})\s*(?<TimeMeridian>am|pm|a.m.|p.m.)){0,1}",
@"(?<Age>[A-Za-z _]*)\s*(?<Year>\d*)(\s*,\s*Moon\s*(?<Moon>\d*),\s*Sun\s*(?<Sun>\d*)\s*(?<Hour>\d{0,2}):(?<Minute>\d{0,2})\s*(?<TimeMeridian>am|pm|a.m.|p.m.)){0,1}"
};

public static List<Regex> RegexList = new List<Regex>();

public long HybrasylTicks
{
get
{
var yearsElapsed = Year;
if (FirstYearInAge(Age) != 1)
yearsElapsed = Year - FirstYearInAge(Age);
return (yearsElapsed * YearTicks + Moon * MoonTicks + Sun * SunTicks + Hour * HourTicks + Minute * MinuteTicks);

}
}


public long TerranTicks => HybrasylTicks / 8;

public static string DefaultAge => Game.Config.Time.ServerStart.DefaultAge != string.Empty ? Game.Config.Time.ServerStart.DefaultAge : "Hybrasyl";
public static int DefaultYear => Game.Config.Time.ServerStart.DefaultYear != 1 ? Game.Config.Time.ServerStart.DefaultYear : 1;

public static bool ValidAge(string age)
{
return Game.Config.Time.Ages.First(a => a.Name == age) != null || DefaultAge == age;
}

public override string ToString()
{
var hour = Hour;
string ampm;
if (hour > 12)
{
hour -= 12;
ampm = "p.m.";
}
else
{
ampm = "a.m.";
}

return
$"{Age} {Year}, {Moon.DisplayWithOrdinal()} moon, {Sun.DisplayWithOrdinal()} sun, {hour}:{Minute.ToString("d2")} {ampm}";
}

public static string CurrentAge
{
get
{
var now = DateTime.Now;
if (Game.Config.Time.Ages.Count == 0)
return DefaultAge;
var currentAge = Game.Config.Time.Ages.First(age => age.DateInAge(now));
return currentAge == null ? DefaultAge : currentAge.Name;
}
}

public static int CurrentYear => Now().Year;

public static int FirstYearInAge(string age)
{
if (!ValidAge(age))
throw new ArgumentException("Age is unknown to server; check time/age configuration in config.xml", age);

var theAge = Game.Config.Time.Ages.First(a => a.Name == age);
if (theAge == null)
return DefaultYear;
return theAge.StartYear != 1 ? 1 : theAge.StartYear;
}

static HybrasylTime()
{
foreach (var regex in RegexStringList)
{
RegexList.Add(new Regex(regex,
RegexOptions.Singleline | RegexOptions.Compiled));
}
}

public HybrasylTime(int year = 1, int moon = 1, int sun = 1, int hour = 1, int minute = 1)
{
Year = year;
Moon = moon;
Sun = sun;
Hour = hour;
Minute = minute;
Age = DefaultAge;
}

public HybrasylTime(string age, int year = 1, int moon = 1, int sun = 1, int hour = 1, int minute = 1)
{
if (!ValidAge(age))
throw new ArgumentException("Age is unknown to server; check time/age configuration in config.xml", nameof(age));
Age = age;
Year = year;
Moon = moon;
Sun = sun;
Hour = hour;
Minute = minute;
}

public void AdvanceDateFromTerranTicks(long ticks)
{
var hurr = ticks * 8;
AdvanceDateFromHybrasylTicks(hurr);
}

public void AdvanceDateFromHybrasylTicks(long ticks)
{
while (ticks > HourTicks)
{
// Year
if (ticks >= YearTicks)
{
ticks -= YearTicks;
Year++;
continue;
}
if (ticks >= MoonTicks)
{
ticks -= MoonTicks;
Moon++;
continue;
}
if (ticks >= SunTicks)
{
ticks -= SunTicks;
Sun++;
continue;
}
if (ticks >= HourTicks)
{
ticks -= HourTicks;
Hour++;
}
}
Minute = (int)(ticks / MinuteTicks);

}

public static HybrasylTime Now()
{
var hybrasylTime = new HybrasylTime();
var terranNow = DateTime.Now;
var timeElapsed = DateTime.Now.Ticks - World.StartDate.Ticks;

if (Game.Config.Time.Ages.Count > 0)
{
var currentAge = Game.Config.Time.Ages.First(age => age.DateInAge(terranNow));
if (currentAge == null)
{
// Age configuration is screwy, simply return default age
Logger.ErrorFormat("Age configuration is nonsensical, using default age");
}
else
{
// Calculate the time that has passed from the start of the current age, to now
timeElapsed = terranNow.Ticks - currentAge.StartDate.Ticks;
hybrasylTime.Age = currentAge.Name;
if (currentAge.StartYear != 1)
hybrasylTime.Year = currentAge.StartYear;
}
}
else
{
hybrasylTime.Age = Game.Config.Time.ServerStart.DefaultAge != string.Empty
? Game.Config.Time.ServerStart.DefaultAge
: DefaultAge;

if (Game.Config.Time.ServerStart.DefaultYear != 1)
hybrasylTime.Year += Game.Config.Time.ServerStart.DefaultYear;
}

hybrasylTime.AdvanceDateFromTerranTicks(timeElapsed);

return hybrasylTime;
}

public static DateTime ConvertToTerran(HybrasylTime hybrasyltime)
{
var thisAge = Game.Config.Time.Ages.First(age => age.Name == hybrasyltime.Age);
return thisAge != null ? new DateTime(thisAge.StartDate.Ticks + hybrasyltime.TerranTicks) : new DateTime(World.StartDate.Ticks + hybrasyltime.TerranTicks);
}

public static HybrasylTime ConvertToHybrasyl(DateTime datetime)
{
if (datetime.Ticks < World.StartDate.Ticks)
throw new ArgumentException("Date passed occurs before known time", nameof(datetime));

var hybrasylTime = new HybrasylTime();
var thisAge = Game.Config.Time.Ages.First(age => age.DateInAge(datetime));
var timeElapsed = datetime.Ticks - World.StartDate.Ticks;

if (thisAge == null)
{
hybrasylTime.Age = DefaultAge;
hybrasylTime.Year = DefaultYear;
}
else
{
hybrasylTime.Age = thisAge.Name;
timeElapsed = datetime.Ticks - thisAge.StartDate.Ticks;
hybrasylTime.Year = thisAge.StartYear;
}

hybrasylTime.AdvanceDateFromTerranTicks(timeElapsed);
return hybrasylTime;
}

public static HybrasylTime FromString(string hybrasyldate)
{
// Supported formats:
// <Age> <Year>, [<cardinal> moon, <cardinal> sun, HH:MM (a.m. | p.m.)]
// <Age <Year>, [Moon <moon>, Sun <sun>, HH:MM (a.m. | p.m.)]

var searchString = hybrasyldate.ToLower();
foreach (var regex in RegexList)
{
var theMatch = regex.Match(hybrasyldate);
if (!theMatch.Success) continue;
var yearInt = Int32.Parse(theMatch.Groups["Year"].Value);
var minuteInt = theMatch.Groups["Minute"].Value != String.Empty
? Int32.Parse(theMatch.Groups["Minute"].Value)
: 0;
var hourInt = theMatch.Groups["Hour"].Value != String.Empty
? Int32.Parse(theMatch.Groups["Hour"].Value)
: 0;
var moonInt = theMatch.Groups["Moon"].Value != String.Empty
? Int32.Parse(theMatch.Groups["Moon"].Value)
: 1;
var sunInt = theMatch.Groups["Sun"].Value != String.Empty
? Int32.Parse(theMatch.Groups["Sun"].Value)
: 1;

if (hourInt < 0 || hourInt > 12 || (hourInt == 12 && theMatch.Groups["TimeMeridian"].Value == "am"))
hourInt = 0;
if (minuteInt < 0 || minuteInt > 59)
minuteInt = 0;

if (theMatch.Groups["TimeMeridian"].Value == "pm" || theMatch.Groups["TimeMeridian"].Value == "p.m.")
{
hourInt += 12;
}

return new HybrasylTime(theMatch.Groups["Age"].Value,
yearInt, moonInt, sunInt, hourInt, minuteInt);
}
throw new ArgumentException("Date / time could not be parsed", nameof(hybrasyldate));
}

public static HybrasylTime FromDateTimeString(string datetimestring)
{
var datetime = DateTime.Parse(datetimestring);
return ConvertToHybrasyl(datetime);
}

}
}

0 comments on commit c25c26f

Please sign in to comment.