Improved Scoreboard look

Improved Scoreboard look

--- Shelter/Mod/Interface/Scoreboard.cs
+++ Shelter/Mod/Interface/Scoreboard.cs
@@ -19,14 +19,97 @@
         protected override void Render()
         {
             if (!PhotonNetwork.inRoom) return;
-            SmartRect rect = new SmartRect(0, -14, Screen.width * 0.35f, 20);
-            foreach (var player in PhotonNetwork.PlayerList) // .OrderBy(x => x.ID).ToList()
-                GUI.Label(rect.OY(15), Entry(player, _animator.LastColor.ToHex()));
-
+
+            _maxWidth = 0;
+            float y = 15;
+            foreach (var player in PhotonNetwork.PlayerList) // O(n)
+            {
+                DrawPlayerInfo(player, y);
+                y += 15;
+            }
+
+            DrawLegenda();
+            y = 15;
+            foreach (var player in PhotonNetwork.PlayerList) // O(n)
+            {
+                DrawPlayerScores(player, y);
+                y += 15;
+            }
+
             if (Time.time - _lastAnimationUpdate < 0.05f)
                 return;
             _animator.ComputeNext();
             _lastAnimationUpdate = Time.time;
+        }
+
+        private void DrawLegenda()
+        {
+            GUI.Label(new Rect(0, 0, _maxWidth, 20), "  Player Info", new GUIStyle(GUI.skin.label) {alignment = TextAnchor.MiddleCenter});
+            GUI.Label(new Rect(_maxWidth + 20, 0, Screen.width, 20), " K/D       max    avg    tot");
+        }
+
+        private void DrawPlayerInfo(in Player player, in float y)
+        {
+            // Compiler computes all const string concatenation.
+            // It looks ugly tho; If we want performance we can switch to it
+            const string SymbolsColor = "#A97AFF";
+            const string IDColor = "#94DC79";
+            const string MCColor = "#8DFF00";
+            const string GuestColor = "#A0A0A0BB";
+
+
+            StringBuilder builder = new StringBuilder(120);
+            builder.AppendFormat("<color={0}>[<color={1}>{2:00}</color>] ", SymbolsColor, IDColor, player.ID);
+
+            builder.Append(ModToString(player.Mod, _animator.LastColor.ToHex()));
+            builder.Append(HumanTypeToString(player));
+            if (player.IsMasterClient)
+                builder.Append("|<color=" + MCColor + ">MC</color>| ");
+            builder.AppendFormat("<color={0}>{1}</color> ", GuestColor, player.Properties.HexName ?? "Unknown");
+            if (!string.IsNullOrEmpty(player.FriendName))
+                builder.AppendFormat("| {0} ", player.FriendName);
+            builder.Append("</color>");
+
+            var playerInfo = builder.ToString();
+
+            var content = new GUIContent(playerInfo);
+            GUI.Label(new Rect(0, y, Screen.width * 0.25f, Screen.height * 0.45f), content);
+
+            GUI.skin.label.CalcMinMaxWidth(content, out _, out float max);
+            _maxWidth = Mathf.Max(max, _maxWidth);
+        }
+
+        private float _maxWidth;
+        private void DrawPlayerScores(in Player player, in float y)
+        {
+            const string NumbersColor = "#5BC0FF";
+            const string TextColor = "#A97AFF";
+
+            StringBuilder builder = new StringBuilder();
+            builder.Append("<color=" + TextColor + ">");
+            {
+                builder.AppendFormat("<color={0}>{1,2}</color>/<color={0}>{2,-2}</color>", NumbersColor, player.Properties.Kills,
+                                                                                player.Properties.Deaths);
+                builder.Append(' ', 3);
+
+                if (player.Properties.MaxDamage > 0)
+                {
+                    builder.AppendFormat("<color={0}>{1,6}</color>", NumbersColor, ReadableDamage(player.Properties.MaxDamage));
+                    builder.Append(' ');
+                }
+
+                if (player.Properties.Kills > 1 && player.Properties.TotalDamage > 0)
+                {
+                    builder.AppendFormat("<color={0}>{1,6}</color>", NumbersColor, ReadableDamage(player.Properties.TotalDamage / player.Properties.Kills));
+                    builder.Append(' ');
+
+                    builder.AppendFormat("<color={0}>{1,6}</color>", NumbersColor, ReadableDamage(player.Properties.TotalDamage));
+                    builder.Append(' ');
+                }
+            }
+            builder.Append("</color>");
+
+            GUI.Label(new Rect(_maxWidth + 20, y, Screen.width * 0.25f, 20), builder.ToString());
         }

         protected override void OnHide()
@@ -34,7 +117,7 @@
             _animator = null;
         }

-        private static string ModToString(CustomMod mod, string color)
+        private static string ModToString(in CustomMod mod, in string color)
         {
             switch (mod)
             {
@@ -92,33 +175,5 @@
                 return $"{damage / 1000f:F1} k";
             return damage.ToString();
         }
-
-        private static string Entry(in Player player, string color)
-        {
-            StringBuilder builder = new StringBuilder();
-            builder.AppendFormat("<color=#672A42>[<color=#DC3052>{0}</color>] ", player.ID);
-
-            // Player info
-            if (player.IsMasterClient)
-                builder.Append("|<color=#8DFF00>MC</color>| ");
-            builder.Append(HumanTypeToString(player));
-            builder.Append(ModToString(player.Mod, color));
-            builder.AppendFormat("<color=#6E8EEB>{0}</color> ", player.Properties.HexName ?? "Unknown");
-            if (!string.IsNullOrEmpty(player.FriendName))
-                builder.AppendFormat("| {0} ", player.FriendName);
-
-            // Average compute
-            var average = 0;
-            if (player.Properties.Kills > 0)
-                average = player.Properties.TotalDamage / player.Properties.Kills;
-
-            // KDA
-            builder.AppendFormat("<color=#31A5E4>{0}</color>|", player.Properties.Kills);
-            builder.AppendFormat("<color=#31A5E4>{0}</color>|", player.Properties.Deaths);
-            builder.AppendFormat("<color=#31A5E4>{0}</color>|", ReadableDamage(player.Properties.MaxDamage));
-            builder.AppendFormat("<color=#31A5E4>{0}</color>|", ReadableDamage(average));
-            builder.AppendFormat("<color=#31A5E4>{0}</color></color>", ReadableDamage(player.Properties.TotalDamage));
-            return builder.ToString();
-        }
     }
 }


Fix for abstract methods reported as they have body

git-tfs-id: [http://falcon:8080/tfs/Projects]$/Phalanger/Main;C5602

--- Source/Core.Parsers/AST/TypeDecl.cs
+++ Source/Core.Parsers/AST/TypeDecl.cs
@@ -355,7 +355,7 @@
             this.name = new Name(name);
             this.signature = new Signature(aliasReturn, formalParams);
             this.typeSignature = new TypeSignature(genericParams);
-            this.body = body.AsArray();
+            this.body = (body != null) ? body.AsArray() : null;
             this.baseCtorParams = baseCtorParams.AsArray();
             this.entireDeclarationPosition = entireDeclarationPosition;
             this.headingEndPosition = headingEndPosition;


Increasing number of retries in case of startup failure.

--- Source/VhdAttach-Service/Service.cs
+++ Source/VhdAttach-Service/Service.cs
@@ -75,7 +75,7 @@
             var todoList = new List<FileWithOptions>(ServiceSettings.AutoAttachVhdList);
             var failedList = new List<FileWithOptions>();

-            for (int i = 0; i < 3; i++) {
+            for (int i = 0; i < 5; i++) {
                 AttachAutomatics(todoList, failedList);
                 if (failedList.Count == 0) { break; } //no failed
                 todoList.Clear();


- added SmartIRC info.

- added SmartIRC info.

--- src/AssemblyInfo.cs
+++ src/AssemblyInfo.cs
@@ -7,12 +7,12 @@
 // change them to the information which is associated with the assembly
 // you compile.

-[assembly: AssemblyTitle("")]
-[assembly: AssemblyDescription("")]
+[assembly: AssemblyTitle("SmartIrc4net")]
+[assembly: AssemblyDescription("IRC library for the .NET Framework")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("")]
-[assembly: AssemblyCopyright("")]
+[assembly: AssemblyProduct("SmartIrc4net")]
+[assembly: AssemblyCopyright("2003 (C) Mirco 'meebey' Bauer")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]

@@ -23,7 +23,7 @@
 // You can specify all values by your own or you can build default build and revision
 // numbers with the '*' character (the default):

-[assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("0.1.0.*")]

 // The following attributes specify the key for the sign of your assembly. See the
 // .NET Framework documentation for more information about signing.


fix assembly info

fix assembly info

--- Synology/Properties/AssemblyInfo.cs
+++ Synology/Properties/AssemblyInfo.cs
@@ -7,9 +7,9 @@
 [assembly: AssemblyTitle("Synology")]
 [assembly: AssemblyDescription("Synology API for .NET")]
 [assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("")]
-[assembly: AssemblyCopyright("Matteo Bruni")]
+[assembly: AssemblyCompany("Caelan")]
+[assembly: AssemblyProduct("Synology")]
+[assembly: AssemblyCopyright("Caelan © 2015")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]


force timers dispatcher

force timers dispatcher

--- TCC.Core/Data/FixedSkillCooldown.cs
+++ TCC.Core/Data/FixedSkillCooldown.cs
@@ -48,11 +48,11 @@
         {
             _dispatcher = d;
             Seconds = 0;
-            _secondsTimer = new DispatcherTimer();
+            _secondsTimer = new DispatcherTimer(DispatcherPriority.Background, _dispatcher);
             _secondsTimer.Interval = TimeSpan.FromSeconds(1);
             _secondsTimer.Tick += _secondsTimer_Tick;

-            _offsetTimer = new DispatcherTimer();
+            _offsetTimer = new DispatcherTimer(DispatcherPriority.Background, _dispatcher);
             _offsetTimer.Tick += _offsetTimer_Tick;

             _type = t;


v0.5.3

--- TCC.Core/Properties/AssemblyInfo.cs
+++ TCC.Core/Properties/AssemblyInfo.cs
@@ -51,5 +51,5 @@
 // È possibile specificare tutti i valori oppure impostare valori predefiniti per i numeri relativi alla revisione e alla build
 // usando l'asterisco '*' come illustrato di seguito:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.5.2.0")]
-[assembly: AssemblyFileVersion("0.5.2.0")]
+[assembly: AssemblyVersion("0.5.3.0")]
+[assembly: AssemblyFileVersion("0.5.3.0")]


Handle exceptions when clearing temp files BECAUSE NO ONE REPORTED IT

--- Torch/Managers/FilesystemManager.cs
+++ Torch/Managers/FilesystemManager.cs
@@ -35,7 +35,20 @@
         private void ClearTemp()
         {
             foreach (var file in Directory.GetFiles(TempDirectory, "*", SearchOption.AllDirectories))
-                File.Delete(file);
+            {
+                try
+                {
+                    File.Delete(file);
+                }
+                catch (UnauthorizedAccessException)
+                {
+                    _log.Debug($"Failed to delete file {file}, it's probably in use by another process'");
+                }
+                catch (Exception ex)
+                {
+                    _log.Warn($"Unhandled exception when clearing temp files. You may ignore this. {ex}");
+                }
+            }
         }

         /// <summary>


VSTS hosted build has some issue with C#7, workaround by changing code

--- UnitTests.Core/Mock/WorkItemMock.cs
+++ UnitTests.Core/Mock/WorkItemMock.cs
@@ -144,8 +144,6 @@
             }
         }

-        public IWorkItemLinkExposedCollection WorkItemLinks => throw new NotImplementedException();
-
         public bool ShouldLimit(RateLimiter limiter)
         {
             return false;
@@ -195,5 +193,11 @@
                 this.IsDirty = true;
             }
         }
+
+        public IWorkItemLinkExposedCollection WorkItemLinks
+        {
+            get { throw new NotImplementedException(); }
+        }
+
     }
 }


Added spec for querying over a read only property.

git-svn-id: 7f05ad86c4f4f5ca50611136d23b835364929451@742 b33fba48-7441-0410-8d5c-f397f7ceaa6c

--- UnitTests/Linq/SupportedQuerying.cs
+++ UnitTests/Linq/SupportedQuerying.cs
@@ -263,5 +263,21 @@
 				public string Value { get; set; }
 			}
 		}
+
+		public class GivenAReadonlyProperty
+		{
+			[Fact]
+			public void WhenQueryingByProperties_ThenSetsThemDirectly()
+			{
+				var foo = Mock.Of<Foo>(x => x.Id == 1);
+
+				Assert.Equal(1, foo.Id);
+			}
+
+			public class Foo
+			{
+				public virtual int Id { get { return 0; } }
+			}
+		}
 	}
 }


AssemblyInfo: Add InternalsVisibleTo for test project

--- UnitsNet/Properties/AssemblyInfo.cs
+++ UnitsNet/Properties/AssemblyInfo.cs
@@ -22,6 +22,7 @@
 using System;
 using System.Reflection;
 using System.Resources;
+using System.Runtime.CompilerServices;

 // General Information about an assembly is controlled through the following
 // set of attributes. Change these attribute values to modify the information
@@ -37,6 +38,9 @@
 [assembly: AssemblyCulture("")]
 [assembly: NeutralResourcesLanguage("")]
 [assembly: CLSCompliant(true)]
+
+// Give access to internal members for testing
+[assembly: InternalsVisibleTo("UnitsNet.Tests")]
 // Version information for an assembly consists of the following four values:
 //
 //      Major Version


call playlistModel.Advance() if nothing is loaded in the engine and

    * src/PlayerInterface.cs:
    * src/PlaylistView.cs: call playlistModel.Advance() if nothing is loaded
    in the engine and playlistView.PlaySelected() fails (pressing play on
    first start will play work) (Ruben Vermeersch)

--- src/PlaylistView.cs
+++ src/PlaylistView.cs
@@ -346,10 +346,10 @@
         {
             CellRendererToggle toggle = (CellRendererToggle)cell;
             AudioCdTrackInfo ti = model.IterTrackInfo(iter) as AudioCdTrackInfo;
-			if (ti != null)
-				toggle.Active = ti.CanRip;
-			else
-				toggle.Active = false;
+            if (ti != null)
+                toggle.Active = ti.CanRip;
+            else
+                toggle.Active = false;
         }

         protected void SyncCellInd(TreeViewColumn tree_column,
@@ -680,18 +680,19 @@
         */

-        public void PlaySelected()
+        public bool PlaySelected()
         {
             TreeIter selIter;

             try {
                 if(!model.GetIter(out selIter, Selection.GetSelectedRows()[0]))
-                    return;
+                    return false;
             } catch(Exception) {
-                return;
+                return false;
             }

             model.PlayIter(selIter);
+            return true;
         }

         public void AddSelectedToPlayList(string name)


Changed from 1.5 to 1.5.1

Changed from 1.5 to 1.5.1

--- AssemblyInfo.cs
+++ AssemblyInfo.cs
@@ -24,4 +24,4 @@
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.5.0.*")]+[assembly: AssemblyVersion("1.5.1.*")]


fixes #28 - set focus on View form when button clicked

--- BackyUI/Main.cs
+++ BackyUI/Main.cs
@@ -148,8 +148,8 @@

         private void btnView_Click(object sender, EventArgs e)
         {
-            //_viewForm.SetDirectoriesAndShow(_settings.Target,  _settings.Sources);
             _viewForm.Show();
+            _viewForm.Focus();
         }

         private void btnStartStop_Click(object sender, EventArgs e)


Gist の関数名変更に対応

Gist の関数名変更に対応

--- Basics/LUT3D.cs
+++ Basics/LUT3D.cs
@@ -30,7 +30,7 @@
 		public LUT3D Reset(int dim) {
             if (_3dlut == null || _dim != dim) {
                 _dim = dim;
-				_3dlut.Destroy();
+				_3dlut.DestroySelf();
                 _3dlut = Create3DLutTex (dim);
             }
             SetDefault ();
@@ -73,7 +73,7 @@

 		#region IDisposable implementation
 		public void Dispose() {
-			_3dlut.Destroy();
+			_3dlut.DestroySelf();
 		}
 		#endregion


Added some ideas

Added some ideas

--- CAC/MainForm.cs
+++ CAC/MainForm.cs
@@ -9,6 +9,9 @@
 {
     public partial class CaC : Form
     {
+        //todo grafy
+        //todo JSON misto XML?
+        //todo použít indexery
         //todo dát související věci k sobě
         public CaC()
         {


Node cleanup

Node cleanup

--- Circuit/Node.cs
+++ Circuit/Node.cs
@@ -11,15 +11,10 @@
     /// </summary>
     public class Node
     {
-        private string name;
         /// <summary>
         /// Name of this node.
         /// </summary>
-        public string Name { get { return name; } set { name = value; } }
-
-        private object tag = null;
-        [Browsable(false)]
-        public object Tag { get { return tag; } set { tag = value; } }
+        public string Name { get; set; }

         public Node() { Name = "_v1"; }

@@ -39,31 +34,22 @@
         /// </summary>
         public IEnumerable<Terminal> Connected { get { return connected; } }

-        private Call v = null;
+        private Call _v;
         /// <summary>
         /// Voltage at this node.
         /// </summary>
-        public Expression V
-        {
-            get
-            {
-                if (!(v is null))
-                    return v;
-                else
-                    return Call.New(name, Component.t);
-            }
-        }
+        public Expression V => _v ?? Call.New(Name, Component.t);

         /// <summary>
         /// Begin analysis with this node in the given context.
         /// </summary>
-        /// <param name="Context"></param>
-        public void BeginAnalysis(string Context)
+        /// <param name="context"></param>
+        public void BeginAnalysis(string context)
         {
-            if (!(v is null))
-                throw new InvalidOperationException("Node '" + name + "' is already part of an analysis.");
+            if (!(_v is null))
+                throw new InvalidOperationException("Node '" + Name + "' is already part of an analysis.");

-            v = Call.New(Context + name, Component.t);
+            _v = Call.New(context + Name, Component.t);
         }

         /// <summary>
@@ -71,7 +57,7 @@
         /// </summary>
         public void EndAnalysis()
         {
-            v = null;
+            _v = null;
         }

         public override string ToString() { return Name; }


Update Form1.cs

Update Form1.cs

--- Client/Form1.cs
+++ Client/Form1.cs
@@ -230,7 +230,6 @@
             try
             {
                 string sURL;
-                //sURL = @"http://www.consult-inform.com/rdp";
                 sURL = setting_url;

                 wrGETURL = WebRequest.Create(sURL);


added a couple more helper methods for generating TimeUUID based on IP and MAC

--- src/GuidGenerator.cs
+++ src/GuidGenerator.cs
@@ -13,7 +13,7 @@
 	{
 		private static readonly Random Random;

-		// number of bytes in guid
+		// number of bytes in uuid
 		private const int ByteArraySize = 16;

 		// multiplex variant info
@@ -95,16 +95,13 @@
 			return (GuidVersion)((bytes[VersionByte] & 0xFF) >> VersionByteShift);
 		}

-		private static byte[] ClockSequence
-		{
-			get
-			{
-				var ts = Stopwatch.GetTimestamp();
-				return new byte[] {
-					(byte)(ts),
-					(byte)(ts >> 0x8)
-				};
-			}
+		public static byte[] GetClockSequenceBytes()
+		{
+			var ts = Stopwatch.GetTimestamp();
+			return new byte[] {
+				(byte)(ts),
+				(byte)(ts >> 0x8)
+			};
 		}

 		public static DateTimeOffset GetDateTimeOffset(Guid guid)
@@ -141,17 +138,37 @@

 		public static Guid GenerateTimeBasedGuid()
 		{
-			return GenerateTimeBasedGuid(DateTimePrecise.UtcNowOffset, ClockSequence, DefaultNode);
+			return GenerateTimeBasedGuid(DateTimePrecise.UtcNowOffset, GetClockSequenceBytes(), DefaultNode);
 		}

 		public static Guid GenerateTimeBasedGuid(DateTime dateTime)
 		{
-			return GenerateTimeBasedGuid(dateTime, ClockSequence, DefaultNode);
+			return GenerateTimeBasedGuid(dateTime, GetClockSequenceBytes(), DefaultNode);
 		}

 		public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime)
 		{
-			return GenerateTimeBasedGuid(dateTime, ClockSequence, DefaultNode);
+			return GenerateTimeBasedGuid(dateTime, GetClockSequenceBytes(), DefaultNode);
+		}
+
+		public static Guid GenerateTimeBasedGuid(DateTime dateTime, PhysicalAddress mac)
+		{
+			return GenerateTimeBasedGuid(dateTime, GetClockSequenceBytes(), GetNodeBytes(mac));
+		}
+
+		public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime, PhysicalAddress mac)
+		{
+			return GenerateTimeBasedGuid(dateTime, GetClockSequenceBytes(), GetNodeBytes(mac));
+		}
+
+		public static Guid GenerateTimeBasedGuid(DateTime dateTime, IPAddress ip)
+		{
+			return GenerateTimeBasedGuid(dateTime, GetClockSequenceBytes(), GetNodeBytes(ip));
+		}
+
+		public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime, IPAddress ip)
+		{
+			return GenerateTimeBasedGuid(dateTime, GetClockSequenceBytes(), GetNodeBytes(ip));
 		}

 		public static Guid GenerateTimeBasedGuid(DateTime dateTime, byte[] clockSequence, byte[] node)


OK, so: kilobit = kb, kiloBYTE = kB. Kb actually would be a Kelvin-bit... which doesn't make a whole lot of sense.

--- src/Kerbalism/Lib.cs
+++ src/Kerbalism/Lib.cs
@@ -704,20 +704,20 @@
 			return (Math.Abs(value) <= 0 ? "none" : BuildString(value.ToString("F0"), append));
 		}

-		///<summary> Format data size, the size parameter is in Mb </summary>
+		///<summary> Format data size, the size parameter is in MB </summary>
 		public static string HumanReadableDataSize(double size)
 		{
 			size *= 1048576.0; //< to bytes
 			if (size < 1.0) return "none";
-			if (size < 1024.0) return BuildString(size.ToString("F0"), " b");
+			if (size < 1024.0) return BuildString(size.ToString("F0"), " B");
 			size /= 1024.0;
-			if (size < 1024.0) return BuildString(size.ToString("F2"), " Kb");
+			if (size < 1024.0) return BuildString(size.ToString("F2"), " kB");
 			size /= 1024.0;
-			if (size < 1024.0) return BuildString(size.ToString("F2"), " Mb");
+			if (size < 1024.0) return BuildString(size.ToString("F2"), " MB");
 			size /= 1024.0;
-			if (size < 1024.0) return BuildString(size.ToString("F2"), " Gb");
+			if (size < 1024.0) return BuildString(size.ToString("F2"), " GB");
 			size /= 1024.0;
-			return BuildString(size.ToString("F2"), " Tb");
+			return BuildString(size.ToString("F2"), " TB");
 		}

 		///<summary> Format data rate, the rate parameter is in Mb/s </summary>


Move enter calls outside of try, the exceptions should propogate.

--- src/Locker/Locker.cs
+++ src/Locker/Locker.cs
@@ -20,9 +20,10 @@
             ReaderWriterLockSlim rwlock,
             Action whileReadLocked)
         {
+            rwlock.EnterReadLock();
+
             try
             {
-                rwlock.EnterReadLock();
                 whileReadLocked();
             }
             catch(Exception e)
@@ -47,9 +48,10 @@
             ReaderWriterLockSlim rwlock,
             Action whileWriteLocked)
         {
+            rwlock.EnterWriteLock();
+
             try
             {
-                rwlock.EnterWriteLock();
                 whileWriteLocked();
             }
             finally
@@ -71,9 +73,10 @@
             ReaderWriterLockSlim rwlock,
             Action whileUpgradeableReadLocked)
         {
+            rwlock.EnterUpgradeableReadLock();
+
             try
             {
-                rwlock.EnterUpgradeableReadLock();
                 whileUpgradeableReadLocked();
             }
             finally


Use BlockCopy on array when possible

Use BlockCopy on array when possible

--- src/MessageReader.cs
+++ src/MessageReader.cs
@@ -470,9 +470,15 @@
 		{
 			int sof = Marshal.SizeOf (primitiveType);
 			Array array = Array.CreateInstance (primitiveType, (int)length);
-			GCHandle handle = GCHandle.Alloc (array, GCHandleType.Pinned);
-			DirectCopy (sof, length, handle);
-			handle.Free ();
+
+			if (endianness == Connection.NativeEndianness) {
+				Buffer.BlockCopy (data, pos, array, 0, (int)(length * sof));
+				pos += (int)length * sof;
+			} else {
+				GCHandle handle = GCHandle.Alloc (array, GCHandleType.Pinned);
+				DirectCopy (sof, length, handle);
+				handle.Free ();
+			}

 			return array;
 		}


Only try to disconnect the remote once.

Only try to disconnect the remote once.

--- PS3Remote.cs
+++ PS3Remote.cs
@@ -237,6 +237,7 @@
             { }

             timerFindRemote.Enabled = true;
+            timerHibernation.Enabled = false;
         }

         public class ButtonData : EventArgs


Add variable to get a sequence of all line separators.

--- src/SilDev/TextEx.cs
+++ src/SilDev/TextEx.cs
@@ -5,7 +5,7 @@
 // ==============================================
 //
 // Filename: TextEx.cs
-// Version:  2018-02-04 04:20
+// Version:  2018-03-23 22:28
 //
 // Copyright (c) 2018, Si13n7 Developments (r)
 // All rights reserved.
@@ -202,6 +202,20 @@
             ///     Carriage Return & Line Feed.
             /// </summary>
             public const string WindowsDefault = "\u000d\u000a";
+
+            /// <summary>
+            ///     Returns a sequence of all line separator characters.
+            /// </summary>
+            public static readonly char[] All =
+            {
+                '\u000d',
+                '\u000c',
+                '\u000a',
+                '\u2028',
+                '\u0085',
+                '\u2029',
+                '\u000b'
+            };
         }
     }
 }


Fix compile error

Fix compile error

--- src/Sprache/Parse.cs
+++ src/Sprache/Parse.cs
@@ -196,7 +196,7 @@
         {
             if (parser == null) throw new ArgumentNullException("parser");

-            return parser.Once().Then(t1 => parser.Many().Select(t1.Concat));
+            return parser.Once().Then(t1 => parser.Many().Select(ts => t1.Concat(ts)));
         }

         /// <summary>
@@ -394,7 +394,7 @@
             if (first == null) throw new ArgumentNullException("first");
             if (second == null) throw new ArgumentNullException("second");

-            return first.Then(f => second.Select(f.Concat));
+            return first.Then(f => second.Select(s => f.Concat(s)));
         }

         /// <summary>
@@ -456,7 +456,7 @@
         /// <returns></returns>
         public static Parser<IEnumerable<T>> Until<T, U>(this Parser<T> parser, Parser<U> until)
         {
-            return parser.Except(until).Many().Then(until.Return);
+            return parser.Except(until).Many().Then(r => until.Return(r));
         }

         /// <summary>


FIx error in summary comment

FIx error in summary comment

--- src/Tar/TarHeader.cs
+++ src/Tar/TarHeader.cs
@@ -865,7 +865,7 @@
 		/// <param name="buffer">The buffer to add to</param>
 		/// <param name="bufferOffset">The index of the first byte to add</param>
 		/// <param name="length">The number of characters/bytes to add</param>
-		/// <returns>The next free index in the <paramref name="buffer/></returns>
+		/// <returns>The next free index in the <paramref name="buffer"/></returns>
 		public static int GetNameBytes(string name, int nameOffset, byte[] buffer, int bufferOffset, int length)
 		{
 			if ( name == null )


Delete DelayDrawing.cs

Delete DelayDrawing.cs

--- DelayDrawing.cs
+++ DelayDrawing.cs
@@ -1,33 +0,0 @@
-using System;
-using System.Collections.Generic;
-using UnityEditor;
-using UnityEngine;
-
-namespace Pangu.Tools
-{
-    public class Drawing
-    {
-        private const int DEFAULT_WINDOW_WIDTH = 1500;
-        public Rect rect;
-        public Action Draw;
-
-        Drawing() { }
-
-        public static Drawing CreateDrawing(Rect rect, Action Draw)
-        {
-            Drawing draw = new Drawing();
-            draw.rect = rect;
-            draw.Draw = Draw;
-            return draw;
-        }
-
-        public static Drawing CreateDrawing(int infoAmount, Action Draw)
-        {
-            Drawing draw = new Drawing();
-            //后面那个是unity添加的间隔
-            draw.rect = new Rect(0, 0, DEFAULT_WINDOW_WIDTH, (EditorGUIUtility.singleLineHeight + 5) * infoAmount + 2 * (infoAmount - 1));
-            draw.Draw = Draw;
-            return draw;
-        }
-    }
-}


Improved BOM detection

Improved BOM detection

--- AngleSharp/Foundation/TextSource.cs
+++ AngleSharp/Foundation/TextSource.cs
@@ -62,7 +62,6 @@
         {
             _baseStream = baseStream;
             _content = new StringBuilder();
-            DetectBOM();
         }

         #endregion
@@ -226,9 +225,9 @@

         #region Helpers

-        void DetectBOM()
-        {
-            var count = _baseStream.Read(_buffer, 0, BufferSize);
+        async Task DetectByteOrderMarkAsync(CancellationToken cancellationToken)
+        {
+            var count = await _baseStream.ReadAsync(_buffer, 0, BufferSize);
             var offset = 0;

             if (count > 2 && _buffer[0] == 0xef && _buffer[1] == 0xbb && _buffer[2] == 0xbf)
@@ -267,8 +266,11 @@

         async Task ExpandBufferAsync(Int64 size, CancellationToken cancellationToken)
         {
+            if (!_finished && _content.Length == 0)
+                await DetectByteOrderMarkAsync(cancellationToken).ConfigureAwait(false);
+
             while (size + _index > _content.Length && !_finished)
-                await ReadIntoBufferAsync(cancellationToken);
+                await ReadIntoBufferAsync(cancellationToken).ConfigureAwait(false);
         }

         async Task ReadIntoBufferAsync(CancellationToken cancellationToken)


Changed some arrays to outvar.

Changed some arrays to outvar.

--- ArkeCLR.Runtime/Files/CliHeaders.cs
+++ ArkeCLR.Runtime/Files/CliHeaders.cs
@@ -151,7 +151,7 @@
                 this.MaxStack = 8;
             }

-            this.Body = file.ReadArray<byte>(this.CodeSize);
+            file.ReadArray(this.CodeSize, out this.Body);

             var sects = new List<MethodDataSectionHeader>();

@@ -205,7 +205,7 @@
                 this.Clauses = file.ReadArray<TinyExceptionHandlingClause>((this.DataSize - 4) / 12).ToArray(c => c.Expand());
             }
             else {
-                this.Clauses = file.ReadArray<ExceptionHandlingClause>((this.DataSize - 4) / 24);
+                file.ReadArray((this.DataSize - 4) / 24, out this.Clauses);
             }
         }
     }


next version bump

next version bump

--- Assets/DeltaDNA/Helpers/Settings.cs
+++ Assets/DeltaDNA/Helpers/Settings.cs
@@ -18,7 +18,7 @@
 {
     public class Settings
     {
-        internal static readonly string SDK_VERSION = "Unity SDK v4.12-beta-1";
+        internal static readonly string SDK_VERSION = "Unity SDK v4.12-beta-2";

         internal static readonly string ENGAGE_API_VERSION = "4";


added Repeat and PingPong

added Repeat and PingPong

--- Assets/Editor/PingPongRepeatTest.cs
+++ Assets/Editor/PingPongRepeatTest.cs
@@ -6,6 +6,7 @@
     [Test]
     public void PingPongTest()
     {
+        // http://docs.unity3d.com/ja/current/ScriptReference/Mathf.PingPong.html
         Assert.That(Mathf.PingPong(-1.75F, 1.0F), Is.EqualTo(0.25F));
         Assert.That(Mathf.PingPong(-1.5F, 1.0F), Is.EqualTo(0.5F));
         Assert.That(Mathf.PingPong(-1.25F, 1.0F), Is.EqualTo(0.75F));
@@ -21,13 +22,42 @@
         Assert.That(Mathf.PingPong(1.25F, 1.0F), Is.EqualTo(0.75F));
         Assert.That(Mathf.PingPong(1.5F, 1.0F), Is.EqualTo(0.5F));
         Assert.That(Mathf.PingPong(1.75F, 1.0F), Is.EqualTo(0.25F));
+    }

+    [Test]
+    public void PingPongTestNegativeLength()
+    {
+        // http://docs.unity3d.com/ja/current/ScriptReference/Mathf.PingPong.html
+        Assert.That(Mathf.PingPong(-1.75F, -1.0F), Is.EqualTo(-1.75F));
+        Assert.That(Mathf.PingPong(-1.5F, -1.0F), Is.EqualTo(-1.5F));
+        Assert.That(Mathf.PingPong(-1.25F, -1.0F), Is.EqualTo(-1.25F));
+        Assert.That(Mathf.PingPong(-1.0F, -1.0F), Is.EqualTo(-1.0F));
+        Assert.That(Mathf.PingPong(-0.75F, -1.0F), Is.EqualTo(-1.25F));
+        Assert.That(Mathf.PingPong(-0.5F, -1.0F), Is.EqualTo(-1.5F));
+        Assert.That(Mathf.PingPong(-0.25F, -1.0F), Is.EqualTo(-1.75F));
+        Assert.That(Mathf.PingPong(0.0F, -1.0F), Is.EqualTo(-2.0F));
+        Assert.That(Mathf.PingPong(0.25F, -1.0F), Is.EqualTo(-1.75F));
+        Assert.That(Mathf.PingPong(0.5F, -1.0F), Is.EqualTo(-1.5F));
+        Assert.That(Mathf.PingPong(0.75F, -1.0F), Is.EqualTo(-1.25F));
+        Assert.That(Mathf.PingPong(1.0F, -1.0F), Is.EqualTo(-1.0F));
+        Assert.That(Mathf.PingPong(1.25F, -1.0F), Is.EqualTo(-1.25F));
+        Assert.That(Mathf.PingPong(1.5F, -1.0F), Is.EqualTo(-1.5F));
+        Assert.That(Mathf.PingPong(1.75F, -1.0F), Is.EqualTo(-1.75F));
+        Assert.That(Mathf.PingPong(2.0F, -1.0F), Is.EqualTo(-2.0F));
+    }
+
+
+    [Test]
+    public void PingPongTestZeroLength()
+    {
+        // http://docs.unity3d.com/ja/current/ScriptReference/Mathf.PingPong.html
         Assert.True(float.IsNaN(Mathf.PingPong(0.5F, 0.0F)));
     }

     [Test]
     public void RepeatTest()
     {
+        // http://docs.unity3d.com/ja/current/ScriptReference/Mathf.Repeat.html
         Assert.That(Mathf.Repeat(-1.75F, 1.0F), Is.EqualTo(0.25F));
         Assert.That(Mathf.Repeat(-1.5F, 1.0F), Is.EqualTo(0.5F));
         Assert.That(Mathf.Repeat(-1.25F, 1.0F), Is.EqualTo(0.75F));
@@ -43,7 +73,33 @@
         Assert.That(Mathf.Repeat(1.25F, 1.0F), Is.EqualTo(0.25F));
         Assert.That(Mathf.Repeat(1.5F, 1.0F), Is.EqualTo(0.5F));
         Assert.That(Mathf.Repeat(1.75F, 1.0F), Is.EqualTo(0.75F));
+    }

+    [Test]
+    public void RepeatTestNegativeLength()
+    {
+        // http://docs.unity3d.com/ja/current/ScriptReference/Mathf.Repeat.html
+        Assert.That(Mathf.Repeat(-1.75F, -1.0F), Is.EqualTo(-0.75F));
+        Assert.That(Mathf.Repeat(-1.5F, -1.0F), Is.EqualTo(-0.5F));
+        Assert.That(Mathf.Repeat(-1.25F, -1.0F), Is.EqualTo(-0.25F));
+        Assert.That(Mathf.Repeat(-1.0F, -1.0F), Is.EqualTo(0.0F));
+        Assert.That(Mathf.Repeat(-0.75F, -1.0F), Is.EqualTo(-0.75F));
+        Assert.That(Mathf.Repeat(-0.5F, -1.0F), Is.EqualTo(-0.5F));
+        Assert.That(Mathf.Repeat(-0.25F, -1.0F), Is.EqualTo(-0.25F));
+        Assert.That(Mathf.Repeat(0.0F, -1.0F), Is.EqualTo(0.0F));
+        Assert.That(Mathf.Repeat(0.25F, -1.0F), Is.EqualTo(-0.75F));
+        Assert.That(Mathf.Repeat(0.5F, -1.0F), Is.EqualTo(-0.5F));
+        Assert.That(Mathf.Repeat(0.75F, -1.0F), Is.EqualTo(-0.25F));
+        Assert.That(Mathf.Repeat(1.0F, -1.0F), Is.EqualTo(0.0F));
+        Assert.That(Mathf.Repeat(1.25F, -1.0F), Is.EqualTo(-0.75F));
+        Assert.That(Mathf.Repeat(1.5F, -1.0F), Is.EqualTo(-0.5F));
+        Assert.That(Mathf.Repeat(1.75F, -1.0F), Is.EqualTo(-0.25F));
+    }
+
+    [Test]
+    public void RepeatTestZeroLength()
+    {
+        // http://docs.unity3d.com/ja/current/ScriptReference/Mathf.Repeat.html
         Assert.True(float.IsNaN(Mathf.Repeat(0.5F, 0.0F)));
     }
-}
+}


adds Controllers as services

adds Controllers as services

--- Assets/Fletch/Lib/IOC/IOCService.cs
+++ Assets/Fletch/Lib/IOC/IOCService.cs
@@ -23,8 +23,8 @@

         /// <summary>
         /// Looks through each child object, seeking for classes that implement
-        /// a interface that ends with 'Service', and adding those to the
-        /// service directory.
+        /// a interface that ends with one of the keywords: 'Service', 'Factory',
+        /// 'Manager', or 'Controller, and adding those to the service directory.
         /// </summary>
         public void Populate ()
         {
@@ -36,9 +36,11 @@
                     {
                         string typeString = type.ToString();

-                        if (typeString.EndsWith( "Service" ) || typeString.EndsWith( "Factory" ) || typeString.EndsWith( "Manager") )
+                        if (typeString.EndsWith( "Service" ) ||
+                            typeString.EndsWith( "Factory" ) ||
+                            typeString.EndsWith( "Manager") ||
+                            typeString.EndsWith( "Controller" ) )
                         {
-
                             ServiceReference serviceReference = new ServiceReference();
                             serviceReference.type = type;
                             serviceReference.reference = component;


Added changeVolume function to MusicPlayer script.

--- Assets/Scripts/Audio/MusicPlayer.cs
+++ Assets/Scripts/Audio/MusicPlayer.cs
@@ -4,12 +4,12 @@

 /*
  * Plays music. Has a few different ways to play.
- * Supports fade in/fade out. Doesn't support layered music.
+ * Supports fade in/fade out and changing the volume.
+ * Doesn't support layered music.
 */

 public class MusicPlayer : MonoBehaviour
 {
-
 	enum PlayingState { NotPlaying, Playing, FadeIn, FadeOut };

 	public static MusicPlayer instance = null; // singleton
@@ -56,7 +56,25 @@
 	{
 		playMusicOnLoop("track_name", 0f); // TODO delete
 	}
-
+
+
+	// Changes the current volume of music to 'volume' (0...1).
+	// If not playing anything, the volume will still change
+	// and it will remain changed when starting to play music the next time.
+	public void changeVolume(float volume)
+	{
+		if (volume > 1.0f)
+		{
+			volume = 1.0f;
+		}
+		else if (volume <= 0f)
+		{
+			volume = 0f;
+			Debug.Log("Muted music player.");
+		}
+		audioSource.volume = volume;
+		maxVolume = volume;
+	}

 	// Plays music on loop. If the same music is already playing,
 	// just continues playing it (doesn't reset).


fixed character movement animations

fixed character movement animations

--- Assets/Scripts/CharacterMovement.cs
+++ Assets/Scripts/CharacterMovement.cs
@@ -69,7 +69,7 @@
         currentState = MovementState.GROUNDED;
         _collider = GetComponent<BoxCollider2D>();
         rigidbody = GetComponent<Rigidbody2D>();
-        _anim = GetComponent<Animator>();
+        _anim = transform.GetChild(1).GetComponent<Animator>();

 		// spawn player
 		Spawn ();
@@ -130,6 +130,7 @@
 			if (Input.GetAxis ("LeftTrigger") > 0.5 || Input.GetButton("LeftTrigger")) {
 				sideSpeed = -1f;
 				transform.localScale = playerLeft;
+                _anim.SetBool("left", true);
                 _anim.SetBool("isWalking", true);
             }
 			// right


Fixed relic being stolen

Fixed relic being stolen

--- Assets/Scripts/GameObjects/Relic.cs
+++ Assets/Scripts/GameObjects/Relic.cs
@@ -48,6 +48,7 @@
                 combat.GainRelic();
                 isErecting = true;
                 CmdRelicStolen();
+                RpcStealRelic();
                 relicRenderer.enabled = false;
                 for (int i = 0; i < lerpPos.Length; i++)
                 {
@@ -95,4 +96,10 @@
     {
         CanvasManager.Instance.SetMessage("A relic was stolen!");
     }
+
+    [ClientRpc]
+    private void RpcStealRelic()
+    {
+        relicRenderer.enabled = false;
+    }
 }


Make SimControlHandler pass up the slider's initial value

--- Assets/Scripts/SimControlHandler.cs
+++ Assets/Scripts/SimControlHandler.cs
@@ -8,10 +8,19 @@
 	public Slider simSpeedSlider;
 	public WorldMap map;

+	private bool initialSet = false;
+
 	// Use this for initialization
 //	void Start () {}
 	// Update is called once per frame
-//	void Update () {}
+	void Update()
+	{
+		if(!initialSet)
+		{
+			simulationSpeedChanged();
+			initialSet = true;
+		}
+	}

 	public void simulationSpeedChanged()
 	{


Added a special merging rule for IsPersisted.

--- Models/Model.cs
+++ Models/Model.cs
@@ -7,6 +7,10 @@

 namespace TogglDoodle.Models
 {
+    /**
+     * TODO: Test for:
+     * - correct MarkDirty behaviour
+     */
     public abstract class Model : INotifyPropertyChanging, INotifyPropertyChanged
     {
         private static Dictionary<Type, Dictionary<long, WeakReference>> modelCache =
@@ -334,6 +338,8 @@

                 // Update our own properties in a specific order:
                 this.RemoteId = other.RemoteId;
+                if (other.IsPersisted)
+                    this.IsPersisted = other.IsPersisted;
                 this.DeletedAt = other.DeletedAt;
                 this.ModifiedAt = other.ModifiedAt;
                 this.IsDirty = other.IsDirty;


test(Nivel1Testes.cs): Remover testes de funcionalidades retiradas.

--- Nivel1Testes.cs
+++ Nivel1Testes.cs
@@ -350,30 +350,6 @@
             Assert.AreEqual(98, rush.Vida);
         }
         [TestMethod]
-        public void RushTemUpgradeDoTipoLendario()
-        {
-            var rush = new Rush();
-            Assert.AreEqual("Lendário", rush.TipoUpgrade);
-        }
-        [TestMethod]
-        public void CanhaoDePlasmaEDoTipoAtaque()
-        {
-            var canhaoDePlasma = new CanhaoDePlasma();
-            Assert.AreEqual("Ataque", canhaoDePlasma.TipoUpgrade);
-        }
-        [TestMethod]
-        public void EscudoDeEnergiaEDoTipoDefesa()
-        {
-            var escudoDeEnergia = new EscudoDeEnergia();
-            Assert.AreEqual("Defesa", escudoDeEnergia.TipoUpgrade);
-        }
-        [TestMethod]
-        public void BotasDeSuperVelocidadeEDoTipoLendario()
-        {
-            var botasDeSuperVelocidade = new BotasDeSuperVelocidade();
-            Assert.AreEqual("Lendário", botasDeSuperVelocidade.TipoUpgrade);
-        }
-        [TestMethod]
         public void RushPodeTerAteDoisUpgradesETerRushComoUpgrade()
         {
             var rush = new Rush();


add string translation to logical view of FormSets
requires loading string packages BEFORE the corresponding form packages

--- ParseLogical.cs
+++ ParseLogical.cs
@@ -44,10 +44,16 @@
             }
         };

+        private struct StringDataBase
+        {
+            public string Language;
+            public List<KeyValuePair<UInt16, string>> Strings;
+        }

         public static List<ParsedHpkNode> ParseHpkPackages(List<HiiPackageBase> Packages)
         {
             List<ParsedHpkNode> result = new List<ParsedHpkNode>();
+            List<StringDataBase> StringDB = new List<StringDataBase>();

             foreach (HiiPackageBase pkg in Packages)
             {
@@ -61,17 +67,22 @@
                             root.Name = "Form Package";
                             result.Add(root);
                             foreach (HPKElement child in root.Origin.Childs)
-                                ParsePackageIfr(child, root, Packages);
+                                ParsePackageIfr(child, root, Packages, StringDB);
+
+                            // clean up..
+                            StringDB = new List<StringDataBase>();
                             break;
                         case EFI_HII_PACKAGE_e.EFI_HII_PACKAGE_STRINGS:
                             UInt16 StringID = 0;
-                            root.Name = "Strings Package \"" + ((HiiPackageString.Payload_t)pkg.Payload).Language + "\"";
+                            StringDataBase db;
+                            db.Language = ((HiiPackageString.Payload_t)pkg.Payload).Language;
+                            db.Strings = new List<KeyValuePair<UInt16, string>>();
+                            StringDB.Add(db);
+
+                            root.Name = "Strings Package \"" + db.Language + "\"";
                             result.Add(root);
                             foreach (HPKElement child in root.Origin.Childs)
-                            {
-                                StringID++;
-                                ParsePackageSibt(child, root, Packages, ref StringID);
-                            }
+                                ParsePackageSibt(child, root, Packages, ref StringID, db);
                             break;
                         default:
                             CreateLogEntryParser(LogSeverity.UNIMPLEMENTED, root.Name);
@@ -89,7 +100,7 @@
             return result;
         }

-        private static void ParsePackageIfr(HPKElement hpkelem, ParsedHpkNode root, List<HiiPackageBase> Packages)
+        private static void ParsePackageIfr(HPKElement hpkelem, ParsedHpkNode root, List<HiiPackageBase> Packages, List<StringDataBase> StringDB)
         {
             ParsedHpkNode branch = new ParsedHpkNode(hpkelem, hpkelem.Name);
             HiiIfrOpCode elem = (HiiIfrOpCode)hpkelem;
@@ -97,45 +108,80 @@
             switch (elem.OpCode)
             {
                 case EFI_IFR_OPCODE_e.EFI_IFR_FORM_SET_OP:
+                    EFI_IFR_FORM_SET hdr = (EFI_IFR_FORM_SET)elem.Header;
+                    ParsedHpkNode leaf = new ParsedHpkNode(hpkelem, "Settings");
+                    ParsedHpkNode setting = new ParsedHpkNode(hpkelem, "");
+                    branch.Name = "FormSet \"" + GetStringOfPackages(StringDB, hdr.FormSetTitle) + "\"";
+                    branch.Childs.Add(leaf);
+                    setting.Name = "Help = " + GetStringOfPackages(StringDB, hdr.Help);
+                    leaf.Childs.Add(setting);
+                    setting.Name = "Guid = " + hdr.Guid.Guid.ToString();
+                    leaf.Childs.Add(setting);
+                    foreach (EFI_GUID classguid in (List<EFI_GUID>)elem.Payload)
+                    {
+                        setting.Name = "ClassGuid = " + classguid.Guid.ToString();
+                        leaf.Childs.Add(setting);
+                    }
                     foreach (HiiIfrOpCode child in elem.Childs)
                     {
                         switch (child.OpCode)
                         {
-                            default: ParsePackageIfr(child, branch, Packages); break;
+                            default: ParsePackageIfr(child, branch, Packages, StringDB); break;
                         }
                     }
                     break;
                 case EFI_IFR_OPCODE_e.EFI_IFR_END_OP: return; // Skip
                 default:
                     foreach (HiiIfrOpCode child in elem.Childs)
-                        ParsePackageIfr(child, branch, Packages);
+                        ParsePackageIfr(child, branch, Packages, StringDB);
                     break; // simply add all others 1:1 when no specific handler exists
             }

             root.Childs.Add(branch);
         }

-        private static void ParsePackageSibt(HPKElement hpkelem, ParsedHpkNode root, List<HiiPackageBase> Packages, ref UInt16 StringID)
+        private static void ParsePackageSibt(HPKElement hpkelem, ParsedHpkNode root, List<HiiPackageBase> Packages, ref UInt16 StringID, StringDataBase db)
         {
             ParsedHpkNode branch = new ParsedHpkNode(hpkelem, hpkelem.Name);
             HiiSibtBlockBase elem = (HiiSibtBlockBase)hpkelem;

             switch (elem.BlockType)
             {
-                case EFI_HII_SIBT_e.EFI_HII_SIBT_STRING_UCS2: branch.Name = StringID.ToString("00000") + " " + ((HiiSibtBlockStringUcs2.Payload_t)elem.Payload).StringText; break;
+                case EFI_HII_SIBT_e.EFI_HII_SIBT_STRING_UCS2:
+                    string StringText = ((HiiSibtBlockStringUcs2.Payload_t)elem.Payload).StringText;
+                    StringID++;
+                    branch.Name = StringID.ToString("00000") + " " + StringText;
+                    db.Strings.Add(new KeyValuePair<ushort, string>(StringID, StringText));
+                    break;
                 case EFI_HII_SIBT_e.EFI_HII_SIBT_SKIP1: StringID += ((EFI_HII_SIBT_SKIP1_BLOCK)elem.Header).SkipCount; return; // Skip
                 case EFI_HII_SIBT_e.EFI_HII_SIBT_SKIP2: StringID += ((EFI_HII_SIBT_SKIP2_BLOCK)elem.Header).SkipCount; return; // Skip
                 case EFI_HII_SIBT_e.EFI_HII_SIBT_END: return; // Skip
                 default:
                     foreach (HiiSibtBlockBase child in elem.Childs)
-                    {
-                        StringID++;
-                        ParsePackageSibt(child, branch, Packages, ref StringID);
-                    }
+                        ParsePackageSibt(child, branch, Packages, ref StringID, db);
                     break; // simply add all others 1:1 when no specific handler exists
             }

             root.Childs.Add(branch);
+        }
+
+        private static string GetStringOfPackages(List<StringDataBase> StringDB, UInt16 StringID, string Language = "en-US")
+        {
+            foreach (StringDataBase db in StringDB)
+            {
+                if (db.Language != Language) continue;
+
+                foreach (KeyValuePair<UInt16, string> entry in db.Strings)
+                {
+                    if (entry.Key == StringID)
+                    {
+                        return entry.Value;
+                    }
+                }
+            }
+
+            CreateLogEntryParser(LogSeverity.WARNING, "StringID " + StringID + " could not be translated!");
+            return "UNKNOWN_STRING_ID(" + StringID + ")";
         }

         private static void CreateLogEntryParser(LogSeverity severity, string msg)


CALayer: Null is allowed in Contents property

--- src/coreanimation.cs
+++ src/coreanimation.cs
@@ -248,7 +248,7 @@
 		[Export ("containsPoint:")]
 		bool Contains (PointF p);

-		[Export ("contents", ArgumentSemantic.Retain)]
+		[Export ("contents", ArgumentSemantic.Retain), NullAllowed]
 		CGImage Contents { get; set; }

 #if MONOMAC


Add new keys

Add new keys

--- src/coreanimation.cs
+++ src/coreanimation.cs
@@ -916,6 +916,17 @@
 		//[Export ("getControlPointAtIndex:values:")]
 		//void getControlPointAtIndex:values: (size_t idx, float[2] ptr);

+		[Field("kCAMediaTimingFunctionLinear")]
+		NSString Linear { get; }
+
+		[Field("kCAMediaTimingFunctionEaseIn")]
+		NSString EaseIn { get; }
+
+		[Field("kCAMediaTimingFunctionEaseOut")]
+		NSString EaseOut { get; }
+
+		[Field("kCAMediaTimingFunctionEaseInEaseOut")]
+		NSString EaseInEaseOut { get; }
 	}

 	[BaseType (typeof (NSObject))]


Apply all properties after cast (looks cleaner)

--- osu.Game.Rulesets.Mania/UI/Column.cs
+++ osu.Game.Rulesets.Mania/UI/Column.cs
@@ -116,9 +116,9 @@
         {
             base.OnNewDrawableHitObject(drawableHitObject);

-            drawableHitObject.AccentColour.Value = AccentColour;
+            DrawableManiaHitObject maniaObject = (DrawableManiaHitObject)drawableHitObject;

-            DrawableManiaHitObject maniaObject = (DrawableManiaHitObject)drawableHitObject;
+            maniaObject.AccentColour.Value = AccentColour;
             maniaObject.CheckHittable = hitPolicy.IsHittable;
         }


Perform next timing point check before ensuring movement

--- osu.Game/Screens/Edit/EditorClock.cs
+++ osu.Game/Screens/Edit/EditorClock.cs
@@ -118,9 +118,14 @@

             seekTime = timingPoint.Time + closestBeat * seekAmount;

+            // limit forward seeking to only up to the next timing point's start time.
+            var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time);
+            if (seekTime > nextTimingPoint?.Time)
+                seekTime = nextTimingPoint.Time;
+
             // Due to the rounding above, we may end up on the current beat. This will effectively cause 0 seeking to happen, but we don't want this.
             // Instead, we'll go to the next beat in the direction when this is the case
-            if (Precision.AlmostEquals(current, seekTime, 1))
+            if (Precision.AlmostEquals(current, seekTime, 0.5f))
             {
                 closestBeat += direction > 0 ? 1 : -1;
                 seekTime = timingPoint.Time + closestBeat * seekAmount;
@@ -129,10 +134,6 @@
             if (seekTime < timingPoint.Time && timingPoint != ControlPointInfo.TimingPoints.First())
                 seekTime = timingPoint.Time;

-            var nextTimingPoint = ControlPointInfo.TimingPoints.FirstOrDefault(t => t.Time > timingPoint.Time);
-            if (seekTime > nextTimingPoint?.Time)
-                seekTime = nextTimingPoint.Time;
-
             // Ensure the sought point is within the boundaries
             seekTime = Math.Clamp(seekTime, 0, TrackLength);
             SeekTo(seekTime);


Remove unnecessary beatmap storage

Remove unnecessary beatmap storage

--- osu.Game/Screens/Menu/IntroScreen.cs
+++ osu.Game/Screens/Menu/IntroScreen.cs
@@ -53,8 +53,6 @@

         private LeasedBindable<WorkingBeatmap> beatmap;

-        public new Bindable<WorkingBeatmap> Beatmap => beatmap;
-
         protected override BackgroundScreen CreateBackground() => new BackgroundScreenBlack();

         protected void StartTrack()
@@ -68,7 +66,7 @@
         private void load(OsuConfigManager config, SkinManager skinManager, BeatmapManager beatmaps, Framework.Game game)
         {
             // prevent user from changing beatmap while the intro is still runnning.
-            beatmap = base.Beatmap.BeginLease(false);
+            beatmap = Beatmap.BeginLease(false);

             MenuVoice = config.GetBindable<bool>(OsuSetting.MenuVoice);
             MenuMusic = config.GetBindable<bool>(OsuSetting.MenuMusic);


Fix MosueUp and HighResolution events not being handled by MenuOverlays.

--- osu.Game/Screens/Play/MenuOverlay.cs
+++ osu.Game/Screens/Play/MenuOverlay.cs
@@ -17,7 +17,7 @@

 namespace osu.Game.Screens.Play
 {
-    public abstract class MenuOverlay : OverlayContainer
+    public abstract class MenuOverlay : OverlayContainer, IRequireHighFrequencyMousePosition
     {
         private const int transition_duration = 200;
         private const int button_height = 70;
@@ -80,6 +80,8 @@

         // Don't let mouse down events through the overlay or people can click circles while paused.
         protected override bool OnMouseDown(InputState state, MouseDownEventArgs args) => true;
+
+        protected override bool OnMouseUp(InputState state, MouseUpEventArgs args) => true;

         protected override bool OnMouseMove(InputState state) => true;


limit local client so it doesn't try to connect to more peers than it has available

--- BitSharp.Node/LocalClient.cs
+++ BitSharp.Node/LocalClient.cs
@@ -118,7 +118,7 @@
                 var unconnectedPeersLocal = this.unconnectedPeers.SafeToList();

                 // get number of connections to attempt
-                var connectCount = maxConnections - (connectedCount + pendingCount);
+                var connectCount = Math.Min(unconnectedCount, maxConnections - (connectedCount + pendingCount));

                 var connectTasks = new Task[connectCount];
                 for (var i = 0; i < connectCount; i++)


Refresh token code so I can keep grabbing new access tokens.


Fix keyboard repeat rate being too fast.

--- osu.Framework/Input/InputManager.cs
+++ osu.Framework/Input/InputManager.cs
@@ -144,6 +144,8 @@
                     if (hasKeyboard)
                         updateKeyboardEvents(inputState);
                 }
+
+                keyboardRepeatTime -= Time.Elapsed;
             }

             base.Update();
@@ -279,8 +281,6 @@

             if (!keyboard.Keys.Any())
                 keyboardRepeatTime = 0;
-            else
-                keyboardRepeatTime -= Time.Elapsed;

             var last = state.Last?.Keyboard;


Looks like multipart messages are working now!

--- client/Assets/Scripts/NetworkMessenger.cs
+++ client/Assets/Scripts/NetworkMessenger.cs
@@ -20,8 +20,8 @@

 	private Queue<NetPacket> message_queue = new Queue<NetPacket>();
-	private Dictionary<uint, List<Multipart>> multipart_cache = new Dictionary<uint, List<Multipart>>();
-	private int multi_groupid = 0;
+	private Dictionary<uint, Multipart[]> multipart_cache = new Dictionary<uint, Multipart[]>();
+	private uint multi_groupid = 0;

 	// Use this for initialization
 	void Start()
@@ -60,13 +60,13 @@
 			msg.message_type = (byte)MsgType.Multipart;
 			//  calculate how many parts we have to split this into
 			int maxsize = 512 - (12+NetPacket.DEFAULT_FRAME_LEN);
-			int parts = (buffer.BaseStream.Length / maxsize) + 1;
+			int parts = ((int)buffer.BaseStream.Length / maxsize) + 1;
 			this.multi_groupid++;
 			int bstart = 0;
 			for (int i = 0; i < parts; i++) {
 				int bend = bstart + maxsize;
 				if (i+1 == parts) {
-					bend = bstart + (buffer.BaseStream.Length % maxsize);
+					bend = bstart + (((int)buffer.BaseStream.Length) % maxsize);
 				}
 				Multipart wrapper = new Multipart();
 				wrapper.ID = (ushort)i;
@@ -202,14 +202,14 @@
 		// Read from message queue and process!
 		// Send updates to each object.
 		Debug.Log("Got message: " + parsedMsg);
-		switch ((MsgType)msg.message_type)
+		switch ((MsgType)np.message_type)
 		{
 			case MsgType.Multipart:
 				Multipart mpmsg = (Multipart)parsedMsg;
 				// 1. If this group doesn't exist, create it
 				if (!this.multipart_cache.ContainsKey(mpmsg.GroupID))
 				{
-					this.multipart_cache[mpmsg.GroupID] = new List<Multipart>(mpmsg.NumParts);
+					this.multipart_cache[mpmsg.GroupID] = new Multipart[mpmsg.NumParts];
 				}
 				// 2. Insert message into group
 				this.multipart_cache[mpmsg.GroupID][mpmsg.ID] = mpmsg;


Fix workingbeatmap's disposal potentially null-refing

--- osu.Game/Beatmaps/WorkingBeatmap.cs
+++ osu.Game/Beatmaps/WorkingBeatmap.cs
@@ -247,7 +247,7 @@

             // cancelling the beatmap load is safe for now since the retrieval is a synchronous
             // operation. if we add an async retrieval method this may need to be reconsidered.
-            beatmapCancellation.Cancel();
+            beatmapCancellation?.Cancel();
             total_count.Value--;
         }


Commit missing pieces

Commit missing pieces

--- osu.Game/Screens/Play/HUDOverlay.cs
+++ osu.Game/Screens/Play/HUDOverlay.cs
@@ -223,11 +223,6 @@
                     ShowHud.Value = false;
                     break;

-                case HUDVisibilityMode.HideDuringBreaks:
-                    // always show during replay as we want the seek bar to be visible.
-                    ShowHud.Value = replayLoaded.Value || !IsBreakTime.Value;
-                    break;
-
                 case HUDVisibilityMode.HideDuringGameplay:
                     // always show during replay as we want the seek bar to be visible.
                     ShowHud.Value = replayLoaded.Value || IsBreakTime.Value;
@@ -284,10 +279,6 @@
                                 break;

                             case HUDVisibilityMode.HideDuringGameplay:
-                                configVisibilityMode.Value = HUDVisibilityMode.HideDuringBreaks;
-                                break;
-
-                            case HUDVisibilityMode.HideDuringBreaks:
                                 configVisibilityMode.Value = HUDVisibilityMode.Always;
                                 break;


ServerListPingPacket is 2 bytes now, Magic field added.

--- Chraft/Net/Packets/Packet.cs
+++ Chraft/Net/Packets/Packet.cs
@@ -2340,15 +2340,19 @@
     /// </summary>
     public class ServerListPingPacket : Packet
     {
-        protected override int Length { get { return 1; } }
-
-        public override void Read(PacketReader stream)
-        {
-        }
-
-        public override void Write()
-        {
-            SetCapacity();
+        protected override int Length { get { return 2; } }
+
+        public byte Magic { get; set; }
+
+        public override void Read(PacketReader stream)
+        {
+            Magic = stream.ReadByte();
+        }
+
+        public override void Write()
+        {
+            SetCapacity();
+            Writer.Write(Magic);
         }
     }


fix: Searches for types in all projects with ModelBuilderDesign

--- Client/ModelBuilderDesign.cs
+++ Client/ModelBuilderDesign.cs
@@ -39,6 +39,32 @@
 			BuildInterfaces(model);

 			return model;
+		}
+
+		// Returns a type from its name.
+		private EnvDTE.CodeType GetCodeType(string name)
+		{
+			// Declarations
+			EnvDTE.CodeType codeType;
+
+			// Tries current project.
+			codeType = CurrentProject.CodeModel.CodeTypeFromFullName(name);
+
+			// Validates code type.
+			if (codeType == null)
+			{
+				// Searches in all available projects.
+				foreach (EnvDTE.Project project in Dte.Solution.Projects)
+				{
+					// Tries the project.
+					codeType = project.CodeModel.CodeTypeFromFullName(name);
+
+					// Found it?
+					if (codeType != null) break;
+				}
+			}
+
+			return codeType;
 		}

 		// Builds a model type.
@@ -70,7 +96,7 @@
 			{
 				// Adds its type.
 				string codeTypeName = codeType.FullName.Substring(0, codeType.FullName.Length - 2);
-				mType.GenericType = BuildMType(CurrentProject.CodeModel.CodeTypeFromFullName(codeTypeName));
+				mType.GenericType = BuildMType(GetCodeType(codeTypeName));
 			}

 			// If List or Task.
@@ -82,8 +108,12 @@
 			// If custom.
 			if (mType.Type == MType.MTType.Custom)
 			{
-				// Checks if type has already been added.
-				if (!Interfaces.Any(it => it.FullName == codeType.FullName)) Interfaces.Add(codeType);
+				// Checks if type has not been added.
+				if (!Interfaces.Any(it => it.FullName == codeType.FullName))
+				{
+					// Adds interface.
+					Interfaces.Add(codeType);
+				}
 			}

 			return mType;
@@ -98,7 +128,7 @@
 			if (startIndex < 0) return null;

 			genericType = genericType.Substring(startIndex + 1, (endIndex - startIndex - 1));
-			EnvDTE.CodeType codeType = CurrentProject.CodeModel.CodeTypeFromFullName(genericType);
+			EnvDTE.CodeType codeType = GetCodeType(genericType);

 			return codeType;
 		}


Fix release compile

Fix release compile

--- Client/PlayerStatusWindow.cs
+++ Client/PlayerStatusWindow.cs
@@ -222,10 +222,10 @@
             for (int i = 0; i < subspaceDisplay.Item2; i++)
             {
                 SubspaceDisplayEntry currentEntry = subspaceDisplay.Item1[i];
+                int diffTime = 0;
                 if (updateSubspace || currentEntry.relativeTimeDisplay == null)
                 {
                     int currentTime = 0;
-                    int diffTime = 0;
                     if (!currentEntry.isUnknown)
                     {
                         if (!currentEntry.isUs)


sort seasons in crop data (#331)

sort seasons in crop data (#331)

--- CropsInAnySeason/ModEntry.cs
+++ CropsInAnySeason/ModEntry.cs
@@ -24,6 +24,9 @@
         /// The seasons for which to override crops.
         private HashSet<string> EnabledSeasons;

+        /// The order that seasons should be listed in crop data.
+        private readonly string[] SeasonOrder = { "spring", "summer", "fall", "winter" };
+
         /// The crop seasons from the game's crop data indexed by harvest IDs.
         /// <remarks>Crops don't store their crop ID, so we can only match them by the harvest ID they produce. This always works for vanilla crops, since different crops never produce the same harvest ID. It's more heuristic for modded crops, which might have duplicate harvest IDs; in that case we just union their seasons to be safe. This lets us revert crops to their normal seasons if the current season is disabled in the mod configuration.</remarks>
         private Lazy<IDictionary<int, string[]>> SeasonsByHarvestID;
@@ -127,7 +130,7 @@
         /// <param name="e">The event arguments.</param>
         private void OnDayEnding(object sender, DayEndingEventArgs e)
         {
-            // remove changes if needed (to let crops die if the next season is disabled)
+            // remove changes before next day is calculated if tomorrow is out of season
             this.UpdateContext(SDate.Now().AddDays(1));
         }

@@ -250,7 +253,12 @@

                 // add seasons
                 if (seasonsByHarvestID.TryGetValue(harvestID, out string[] cropSeasons))
-                    seasonsByHarvestID[harvestID] = cropSeasons.Union(rawSeasons).ToArray();
+                {
+                    seasonsByHarvestID[harvestID] = cropSeasons
+                        .Union(rawSeasons)
+                        .OrderBy(season => Array.IndexOf(this.SeasonOrder, season))
+                        .ToArray();
+                }
                 else
                     seasonsByHarvestID[harvestID] = rawSeasons;
             }


Updated Unity Script: Fixed error when using existing and new components together

--- unity/NetworkModel.cs
+++ unity/NetworkModel.cs
@@ -701,7 +701,11 @@
                 GameObject go = null;
                 if (config.EXISTINGCOMP)
                 {
-                    go = FindTransform(config.transform, name).gameObject;
+                    Transform tmp = FindTransform(config.transform, name);
+                    if (tmp != null)
+                    {
+                        go = tmp.gameObject;
+                    }
                 }
                 if (go == null)
                 {
@@ -892,7 +896,7 @@
             if (this.Contains(assetName))
             {
                 AssetNode tmp = (AssetNode)this[assetName];
-                if (tmp.asset.GetType() == type)
+                if (tmp.asset != null && tmp.asset.GetType() == type)
                 {
                     node = tmp;
                     return true;
@@ -1906,7 +1910,6 @@
                 }

                 UnityEngine.Material material = (UnityEngine.Material)asset;
-
                 Shader shader = Shader.Find(this.n);
                 if (shader != null)
                 {


Added test case to ensure that DateTime.HasTime is properly set when calling Evaluate()

--- DDay.iCal.Test/Recurrence.cs
+++ DDay.iCal.Test/Recurrence.cs
@@ -79,7 +79,9 @@
             r.RRULE38();
             r.RRULE39();
             r.RRULE40();
-            r.RRULE41();
+            r.RRULE41();
+
+            r.EVALUATE1();
         }

         /// <summary>
@@ -2076,6 +2078,26 @@
             Assert.IsTrue(evt.Periods.Count == DateTimes.Length, "There should be exactly " + DateTimes.Length + " occurrences; there were " + evt.Periods.Count);
         }

-
+        /// <summary>
+        /// Ensures that the StartTime and EndTime of periods have
+        /// HasTime set to true if the beginning time had HasTime set
+        /// to false.
+        /// </summary>
+        [Test, Category("Recurrence")]
+        public void EVALUATE1()
+        {
+            iCalendar iCal = new iCalendar();
+            Event evt = iCal.Create<Event>();
+            evt.Summary = "Event summary";
+
+            // Start at midnight, UTC time
+            evt.Start = DateTime.SpecifyKind(DateTime.Today, DateTimeKind.Utc);
+
+            evt.AddRecurrence(new Recur("FREQ=MINUTELY;INTERVAL=10;COUNT=5"));
+            List<Period> periods = evt.Evaluate(DateTime.Today.AddDays(1), DateTime.Today.AddDays(2));
+
+            foreach (Period p in periods)
+                Assert.IsTrue(p.StartTime.HasTime, "All recurrences of this event should have a time set.");
+        }
     }
 }


Fixed a bug with recurrence where hours/minutes/seconds were sometimes not calculated correctly

git-svn-id: 95472bb50cfb75dbf91fed26dc933cae36d5c45c@257 1ca100b6-b014-4248-a4f8-5dbb9f49130a

--- DDay.iCal/DataTypes/Recur.cs
+++ DDay.iCal/DataTypes/Recur.cs
@@ -511,13 +511,16 @@
                 ByDay.Count == 0)
                 this.ByDay.Add(new DaySpecifier(StartDate.Value.DayOfWeek));
             if (Frequency > FrequencyType.SECONDLY &&
-                this.BySecond.Count == 0)
+                this.BySecond.Count == 0 &&
+                StartDate.HasTime /* NOTE: Fixes a bug where all-day events have BySecond/ByMinute/ByHour added incorrectly */)
                 this.BySecond.Add(StartDate.Value.Second);
             if (Frequency > FrequencyType.MINUTELY &&
-                this.ByMinute.Count == 0)
+                this.ByMinute.Count == 0 &&
+                StartDate.HasTime /* NOTE: Fixes a bug where all-day events have BySecond/ByMinute/ByHour added incorrectly */)
                 this.ByMinute.Add(StartDate.Value.Minute);
-            if (Frequency > FrequencyType.HOURLY &&
-                this.ByHour.Count == 0)
+            if (Frequency > FrequencyType.HOURLY &&
+                this.ByHour.Count == 0 &&
+                StartDate.HasTime /* NOTE: Fixes a bug where all-day events have BySecond/ByMinute/ByHour added incorrectly */)
                 this.ByHour.Add(StartDate.Value.Hour);
             // If neither BYDAY, BYMONTHDAY, or BYYEARDAY is specified,
             // default to the current day of month
@@ -804,7 +807,7 @@
         }

         protected void FillDays(TimeCalculation TC)
-        {
+        {
             foreach (int day in TC.Days)
             {
                 TC.Day = day;
@@ -814,27 +817,51 @@

         protected void FillHours(TimeCalculation TC)
         {
-            foreach (int hour in TC.Hours)
-            {
-                TC.Hour = hour;
+            if (TC.Hours.Count > 0)
+            {
+                foreach (int hour in TC.Hours)
+                {
+                    TC.Hour = hour;
+                    FillMinutes(TC);
+                }
+            }
+            else
+            {
+                TC.Hour = 0;
                 FillMinutes(TC);
             }
         }

         protected void FillMinutes(TimeCalculation TC)
         {
-            foreach (int minute in TC.Minutes)
-            {
-                TC.Minute = minute;
+            if (TC.Minutes.Count > 0)
+            {
+                foreach (int minute in TC.Minutes)
+                {
+                    TC.Minute = minute;
+                    FillSeconds(TC);
+                }
+            }
+            else
+            {
+                TC.Minute = 0;
                 FillSeconds(TC);
             }
         }

         protected void FillSeconds(TimeCalculation TC)
         {
-            foreach (int second in TC.Seconds)
-            {
-                TC.Second = second;
+            if (TC.Seconds.Count > 0)
+            {
+                foreach (int second in TC.Seconds)
+                {
+                    TC.Second = second;
+                    TC.Calculate();
+                }
+            }
+            else
+            {
+                TC.Second = 0;
                 TC.Calculate();
             }
         }
@@ -943,47 +970,9 @@
             if (StartDate > FromDate)
                 FromDate = StartDate;

-            /*
-            // If the frequency is WEEKLY, and the interval is greater than 1,
-            // then we need to ensure that the StartDate occurs in one of the
-            // "active" weeks, to ensure that we properly "step" through weeks.
-            // NOTE: Fixes bug #1741093 - WEEKLY frequency eval behaves strangely
-            if (Frequency == FrequencyType.WEEKLY &&
-                Interval > 1)
-            {
-                // Get the week of year of the time frame we want to calculate
-                int firstEvalWeek = _Calendar.GetWeekOfYear(FromDate.Value, System.Globalization.CalendarWeekRule.FirstFourDayWeek, Wkst);
-
-                // Count backwards in years, calculating how many weeks' difference we have between
-                // start date and evaluation period.
-                Date_Time evalDate = FromDate;
-                while (evalDate.Year > StartDate.Year)
-                {
-                    firstEvalWeek += _Calendar.GetWeekOfYear(new DateTime(evalDate.Year - 1, 12, 31), System.Globalization.CalendarWeekRule.FirstFourDayWeek, Wkst);
-                    evalDate = evalDate.AddYears(-1);
-                }
-
-                // Determine the difference, in weeks, between the start date and the evaluation period.
-                int startWeek = _Calendar.GetWeekOfYear(StartDate.Value, System.Globalization.CalendarWeekRule.FirstFourDayWeek, Wkst);
-                int weeksDifference = firstEvalWeek - startWeek;
-
-                // Determine how many weeks the evaluation period needs to change
-                // in order to "align" to the start date week, given the specified interval.
-                int offset = 0;
-                while (weeksDifference % Interval != 0)
-                {
-                    weeksDifference--;
-                    offset++;
-                }
-
-                // Offset the week back to a "compatible" week for evaluation
-                FromDate = FromDate.AddDays(-offset * 7);
-            }*/
-
             // If the interval is greater than 1, then we need to ensure that the StartDate occurs in one of the
             // "active" days/weeks/months/years/etc. to ensure that we properly "step" through the interval.
             // NOTE: Fixes bug #1741093 - WEEKLY frequency eval behaves strangely
-            if (Interval > 1)
             {
                 // Determine the difference between our two dates, using our frequency as the UNIT.
                 long difference = DateUtils.DateDiff(this.Frequency, StartDate, FromDate, Wkst);
@@ -1010,7 +999,7 @@
             foreach (Date_Time occurrence in r.GetOccurrences(FromDate.Copy(), ToDate, r.Count))
             {
                 // NOTE:
-                // Used to be DateTime.AddRange(r.GetOccurrences(FromDate.Copy(), ToDate, r.Count))
+                // Used to be DateTimes.AddRange(r.GetOccurrences(FromDate.Copy(), ToDate, r.Count))
                 // By doing it this way, fixes bug #19.
                 if (!DateTimes.Contains(occurrence))
                     DateTimes.Add(occurrence);
@@ -1035,7 +1024,7 @@
             foreach (Date_Time dt in DateTimes)
                 dt.MergeWith(StartDate);

-            // Ensure that DateTimes have an assigned time if they occur less than dailyB
+            // Ensure that DateTimes have an assigned time if they occur less than daily
             foreach (Date_Time dt in DateTimes)
             {
                 if (Frequency < FrequencyType.DAILY)


Build: Fix typo

Build: Fix typo

--- tools/build/BuildDefinition.cs
+++ tools/build/BuildDefinition.cs
@@ -299,7 +299,7 @@
                 {
                     body = isIssue
                         ? $"A fix for this issue has been released in [version {version.NuGetVersion}](https://github.com/{GitHubRepository}/releases/tag/v{version.NuGetVersion})."
-                        : $"This heature has been released in [version {version.NuGetVersion}](https://github.com/{GitHubRepository}/releases/tag/v{version.NuGetVersion})."
+                        : $"This feature has been released in [version {version.NuGetVersion}](https://github.com/{GitHubRepository}/releases/tag/v{version.NuGetVersion})."
                 });

                 commentResponse.EnsureSuccessStatusCode();


bumped ver

bumped ver

--- SolutionInfo.cs
+++ SolutionInfo.cs
@@ -7,4 +7,4 @@
 [assembly: AssemblyCulture("")]

-[assembly: AssemblyVersion("1.1.0.17")]+[assembly: AssemblyVersion("1.1.0.18")]


Test the return of Program in case something went wrong

--- tests/TestCommitFiltering.cs
+++ tests/TestCommitFiltering.cs
@@ -28,11 +28,11 @@
             var test = InitializeTest();

             // Test directly the main program as we want to test also command line parameters
-            Program.Main("--commit-filter",
+            Assert.Equal(0, Program.Main("--commit-filter",
                 @"commit.Message += ""This is a test"";",
                 "--repo-dir", test.Path,
                 "--branch", NewBranch,
-                @"HEAD");
+                @"HEAD"));

             var repo = test.Repo;
             var headNewMaster = AssertBranchRef(repo);
@@ -69,11 +69,11 @@
             var test = InitializeTest();

             // Test directly the main program as we want to test also command line parameters
-            Program.Main("--commit-filter",
+            Assert.Equal(0, Program.Main("--commit-filter",
                 @"commit.Message += ""This is a test"";",
                 "--repo-dir", test.Path,
                 "--branch", NewBranch,
-                @"HEAD~4..HEAD");
+                @"HEAD~4..HEAD"));

             var repo = test.Repo;
             var headNewMaster = AssertBranchRef(repo);
@@ -119,12 +119,12 @@
             var test = InitializeTest();

             // Test directly the main program as we want to test also command line parameters
-            Program.Main("--commit-filter",
+            Assert.Equal(0, Program.Main("--commit-filter",
                 @"commit.Message += ""This is a test"";",
                 "--repo-dir", test.Path,
                 "--branch", NewBranch,
                 "--detach",
-                @"HEAD~2..HEAD");
+                @"HEAD~2..HEAD"));

             var repo = test.Repo;
             var headNewMaster = AssertBranchRef(repo);
@@ -168,11 +168,11 @@
             var test = InitializeTest();

             // Test directly the main program as we want to test also command line parameters
-            Program.Main("--commit-filter",
+            Assert.Equal(0, Program.Main("--commit-filter",
                 @"commit.Discard = !commit.Message.Contains(""test.bin""); if (!commit.Discard) { commit.AuthorName=""NewAuthor""; commit.AuthorEmail = ""test@gmail.com""; commit.CommitterName =""NewCommitter""; commit.CommitterEmail = ""test2@gmail.com""; }",
                 "--repo-dir", test.Path,
                 "--branch", NewBranch
-                );
+                ));

             var repo = test.Repo;
             var headNewMaster = AssertBranchRef(repo);


Bump to version 0.1.4.

Bump to version 0.1.4.

--- SolutionInfo.cs
+++ SolutionInfo.cs
@@ -1,6 +1,6 @@
 using System.Reflection;

-[assembly: AssemblyVersion("0.1.3.0")]
+[assembly: AssemblyVersion("0.1.4.0")]
 [assembly: AssemblyCompany("")]
 [assembly: AssemblyCopyright("Copyright 2016 Ed Ball")]
 [assembly: AssemblyTrademark("")]


Cutting a new version

Cutting a new version

--- SolutionInfo.cs
+++ SolutionInfo.cs
@@ -7,7 +7,7 @@
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]

-[assembly: AssemblyVersion("0.2.1.0")]
-[assembly: AssemblyFileVersion("0.2.1.0")]
+[assembly: AssemblyVersion("0.2.2.0")]
+[assembly: AssemblyFileVersion("0.2.2.0")]

 [assembly: ComVisible(false)]


tested Op 	modified:   Dragon/UnitTests/TestExpr.cs

--- Dragon/UnitTests/TestExpr.cs
+++ Dragon/UnitTests/TestExpr.cs
@@ -40,5 +40,30 @@
             Assert.AreEqual(2, another_temp.Number);
             Assert.AreEqual("t2", another_temp.ToString());
         }
+
+        [TestMethod]
+        public void TestOp()
+        {
+            var plus = new Op(new Token('+'), Dragon.Type.Int);
+            plus.Reduce();
+
+            var mult = new Op(new Token('*'), Dragon.Type.Float);
+            mult.Reduce();
+
+            var grte = new Op(Word.ge, Dragon.Type.Char);
+            grte.Reduce();
+
+            var and = new Op(Word.and, Dragon.Type.Int);
+            and.Reduce();
+
+            //output:
+            //Test Name:	TestOp
+            //Test Outcome:	Passed
+            //Result StandardOutput:
+            //    t1 = +
+            //    t2 = *
+            //    t3 = >=
+            //    t4 = &&
+        }
     }
 }


OK. We're done.

OK. We're done.

--- SimpleSSO.cs
+++ SimpleSSO.cs
@@ -27,6 +27,7 @@
         public readonly HMAC hmac;
         public readonly bool resEncAll;
         public readonly EncType resEncoding;
+        public readonly TimeSpan lifetime;

         public enum EncType { HEXSTRING, BASE64 };

@@ -45,7 +46,9 @@
         /// </param>
         /// <param name="resEncoding">Either <c>Base64</c> or <c>Hex String</c>
         /// representation of the (partialy) binary result to returm.</param>
-        public SimpleSSO(Encoding charEncoding, HMAC hmac, bool resEncAll, EncType resEncoding)
+        /// <param name="lifetime">A <c>TimeSpan</c> for the validity of the
+        /// created token.</param>
+        public SimpleSSO(Encoding charEncoding, HMAC hmac, bool resEncAll, EncType resEncoding, TimeSpan lifetime)
         {
             if (charEncoding == null || hmac == null)
                 throw new ArgumentNullException();
@@ -56,6 +59,7 @@
             this.hmac = hmac;
             this.resEncAll = resEncAll;
             this.resEncoding = resEncoding;
+            this.lifetime = lifetime;
         }

         /// <summary>
@@ -66,6 +70,7 @@
         /// provided <paramref name="key"/>,</description></item>
         /// <item><description>text-encoding the hmac only</description></item>
         /// <item><description>result encoding as hex string</description></item>
+        /// <item><description>Five minutes expiration time</description></item>
         /// </list>
         /// </summary>
         /// <param name="key">The secret key phrase.</param>
@@ -73,7 +78,8 @@
             Encoding.UTF8,
             new HMACSHA256(Encoding.UTF8.GetBytes(key)),
             false,
-            EncType.HEXSTRING) { }
+            EncType.HEXSTRING,
+            TimeSpan.FromMinutes(5)) { }

         public string[] CreateTokens(string data, params string[] more)
         {
@@ -102,30 +108,34 @@

         public bool IsValid(string token, params string[] more)
         {
+            return DecodeData(token, more).Length > 0;
+        }
+
+        public string[] DecodeData(string token, params string[] more)
+        {
             try
             {
-                Validate(token, more);
-                return true;
+                return Validate(token, more);
             }
             catch (ArgumentException) { }
             catch (CryptographicException) { }
+            catch (FormatException) { }
             catch (System.Security.Authentication.InvalidCredentialException) { }
             catch (TimeoutException) { }
-
-            return false;
-        }
-
-        public void Validate(string token, params string[] more)
+
+            return new string[0];
+        }
+
+        public string[] Validate(string token, params string[] more)
         {
             if (String.IsNullOrEmpty(token))
                 throw new ArgumentNullException("token");
             else if (more.Length == 1)
                 throw new ArgumentException("There may be either one token or three or more tokens.", "more");
-            else if (more.Length == 0 && token.LastIndexOf(':') == token.Length)
-                throw new ArgumentException("No hash found in token.", "token");
-
-            string message, hash;
-            byte[] ba;
+
+            string data = null,
+                   encodedText;
+            byte[] ba, hash;
             if (more.Length == 0)
             {
                 // Note: Correctness depens on encoding not using ':',
@@ -139,25 +149,46 @@
                 {
                     throw new ArgumentException("No user data found in token.", "token");
                 }
-                else if (pos > 0)
+                else if (pos > 1)
                 {
-                    hash = token.Substring(pos);
-                    message = token.Substring(0, pos - 1);
+                    encodedText = token.Substring(pos);
+                    data = token.Substring(0, pos - 1);
                 }
-                else
+                else // pos == 0
                 {
-                    hash = token;
+                    encodedText = token;
                 }
-
             }
             else
             {
-                hash = more[more.Length - 1];
-                message = ConcatenateStrings(token, more, 0, more.Length - 1);
-            }
-
-            ba = Decode(hash);
-
+                encodedText = more[more.Length - 1];
+                data = ConcatenateStrings(token, more, 0, more.Length - 1);
+            }
+
+            if (data == null) // A single encoded token
+            {
+                ba = Decode(encodedText);
+                if (ba.Length <= hmac.HashSize / 8)
+                    throw new ArgumentException("Invalid token.", "token");
+                hash = new byte[hmac.HashSize / 8];
+                Array.Copy(ba, ba.Length - hash.Length, hash, 0, hash.Length);
+                Array.Resize(ref ba, ba.Length - hash.Length);
+                data = charEncoding.GetString(ba);
+            }
+            else
+            {
+                hash = Decode(encodedText);
+                if (hash.Length != hmac.HashSize / 8)
+                    throw new ArgumentException("Invalid token.", "token");
+                ba = charEncoding.GetBytes(data);
+            }
+
+            if (!ArrayEquals(hmac.ComputeHash(ba), hash))
+                throw new System.Security.Authentication.InvalidCredentialException();
+            else if (IsExpired(data))
+                throw new TimeoutException("Token expired.");
+
+            return data.Split(':');
         }

         private string CreateMessage(string data, string[] more)
@@ -216,9 +247,58 @@
             throw new NotSupportedException();
         }

-        private byte[] Decoce(string p)
-        {
+        private byte[] Decode(string encodedText)
+        {
+            switch (resEncoding)
+            {
+                case EncType.HEXSTRING:
+                    byte[] ba = new byte[encodedText.Length / 2];
+                    for (int i = 0; i < ba.Length; i++)
+                    {
+                        ba[i] = (byte)(HexValue(encodedText[2 * i]) << 4 + HexValue(encodedText[2 * i + 1]));
+                    }
+                    return ba;
+
+                case EncType.BASE64:
+                    return Convert.FromBase64String(encodedText);
+
+                default:
+                    break;
+            }
+            // We should never get here
             throw new NotImplementedException();
+        }
+
+        private int HexValue(char c)
+        {
+            int b = c - '0';
+            if (b > 9) b -= 7;
+            return b;
+        }
+
+        private bool ArrayEquals(byte[] a1, byte[] a2)
+        {
+            if (ReferenceEquals(a1, a2))
+                return true;
+
+            if (a1 == null || a2 == null)
+                return false;
+
+            if (a1.Length != a2.Length)
+                return false;
+
+            for (int i = 0; i < a1.Length; i++)
+                if (a1[i] != a2[i])
+                    return false;
+
+            return true;
+        }
+
+        private bool IsExpired(string data)
+        {
+            int pos = data.LastIndexOf(':') + 1;
+            int ms = Convert.ToInt32(data.Substring(pos));
+            return (DateTime.Now - new DateTime(1970, 1, 1) - lifetime).TotalMilliseconds > ms;
         }
     }
 }


async method

async method

--- Speechs/run.csx
+++ Speechs/run.csx
@@ -17,7 +17,7 @@
 using Microsoft.WindowsAzure.Storage;
 using Microsoft.WindowsAzure.Storage.Table;

-public static Task<Stream> Run(string queueItem,
+public static async Task<Stream> Run(string queueItem,
     DateTimeOffset expirationTime,
     DateTimeOffset insertionTime,
     DateTimeOffset nextVisibleTime,


Fix for shared code name changes

Fix for shared code name changes

--- FTAnalyser/Forms/MainForm.cs
+++ FTAnalyser/Forms/MainForm.cs
@@ -1962,13 +1962,13 @@
                         DatabaseHelper dbh = DatabaseHelper.Instance;
                         if (dbh.StartBackupRestoreDatabase())
                         {
-                            File.Copy(dbh.Filename, dbh.CurrentFilename, true); // copy exisiting file to safety
+                            File.Copy(dbh.DatabaseFile, dbh.CurrentFilename, true); // copy exisiting file to safety
                             zip.ExtractAll(dbh.DatabasePath, ExtractExistingFileAction.OverwriteSilently);
                             if (dbh.RestoreDatabase(new Progress<string>(value => { rtbOutput.AppendText(value); })))
                                 MessageBox.Show("Database restored from " + restoreDatabase.FileName, "FTAnalyzer Database Restore Complete");
                             else
                             {
-                                File.Copy(dbh.CurrentFilename, dbh.Filename, true);
+                                File.Copy(dbh.CurrentFilename, dbh.DatabaseFile, true);
                                 dbh.RestoreDatabase(new Progress<string>(value => { rtbOutput.AppendText(value); })); // restore original database
                                 failed = true;
                             }


Accounted for more edge cases.

Accounted for more edge cases.

--- FTPizza/ConnectionManager.cs
+++ FTPizza/ConnectionManager.cs
@@ -19,6 +19,7 @@
         private int userIndex;
         private string answer;
         private string selectedUser;
+        private bool newUser;

         public ConnectionManager()
         {
@@ -29,12 +30,14 @@
             try
             {
                 connectionFile = File.ReadAllLines(@"connection.txt");
+                newUser = false;
             }
             catch (FileNotFoundException)
             {
                 //Calls GC on object after creation to allow access other processes
                 File.Create("connection.txt").Dispose();
                 connectionFile = new string[] { };
+                newUser = true;
             }

         }
@@ -48,31 +51,38 @@
                 throw new Exception("ERROR: connection.txt is corrupt.");
             }

-            Console.WriteLine("\n/////////////////////////////////////");
-            Console.WriteLine("The following users are available:");
-            Console.WriteLine();
-            foreach (string item in connectionFile)
+            if (!newUser)
             {
-                if (item.Contains("user="))
+                Console.WriteLine("\n/////////////////////////////////////");
+                Console.WriteLine("The following users are available:");
+                Console.WriteLine();
+                foreach (string item in connectionFile)
                 {
-                    Console.WriteLine("--> '" + item.Replace("user=", "") + "'");
+                    if (item.Contains("user="))
+                    {
+                        Console.WriteLine("--> '" + item.Replace("user=", "") + "'");
+                    }
                 }
+                Console.WriteLine();
             }
-            Console.WriteLine();
         }

         public void selectUser()
         {
             connectionInfo = new List<string>();
-            Console.WriteLine("Enter the name of the user you'd like to connect with, \notherwise enter 'create' to create a new user: ");
-            answer = Console.ReadLine();
+
+            if(!newUser && connectionFile.Length > 0)
+            {
+                Console.WriteLine("Enter the name of the user you'd like to connect with, \notherwise enter 'create' to create a new user: ");
+                answer = Console.ReadLine();
+            }

             foreach (string item in connectionFile)
             {
                 connectionInfo.Add(item);
             }

-            if (answer.Equals("create"))
+            if (newUser || connectionFile.Length < 3 || answer.Equals("create"))
             {
                 Console.WriteLine("/////////////////////////////////////");
                 Console.WriteLine("Creating a new user...");
@@ -113,7 +123,7 @@

         public void saveUserInfo()
         {
-            if (answer.Equals("create"))
+            if (newUser || connectionFile.Length < 3 || answer.Equals("create"))
             {
                 string[] newConnectionInfo = new string[connectionInfo.Count];
                 int index = 0;
@@ -129,7 +139,7 @@

         public string getFtpUrl()
         {
-            if (answer.Equals("create"))
+            if (newUser || connectionFile.Length < 3 || answer.Equals("create"))
             {
                 return ftpUrl;
             }
@@ -141,7 +151,7 @@

         public string getFtpUsername()
         {
-            if (answer.Equals("create"))
+            if (newUser || connectionFile.Length < 3 || answer.Equals("create"))
             {
                 return ftpUsername;
             }
@@ -153,7 +163,7 @@

         public string getFtpPassword()
         {
-            if (answer.Equals("create"))
+            if (newUser || connectionFile.Length < 3 || answer.Equals("create"))
             {
                 return ftpPassword;
             }


Add initialize type

Add initialize type

--- FuzzyCore/Initialize/Init.cs
+++ FuzzyCore/Initialize/Init.cs
@@ -23,17 +23,20 @@
                 return Host;
             }
         }
-
-        public static String ProgramJsonPath;
         ConsoleMessage Message = new ConsoleMessage();
         FuzzyServer Server;
         ServiceHost Host;
-        public Init(string ProgramJsonPathArg,Action<Client> AcceptTask, Action<string, Client> ReceiveTask, string Ip = "127.0.0.1" , string Port = "111" , bool StartServer = true ,bool StartWCFService = true,bool StartReceive = true,bool StartAccept = true)
+        public Init(string ProgramJsonPathArg,Action<Client> AcceptTask, Action<string, Client> ReceiveTask,  InitType.Type initilizeType = InitType.Type.BASIC, string Ip = "127.0.0.1" , string Port = "111" , bool StartServer = true ,bool StartWCFService = true,bool StartReceive = true,bool StartAccept = true)
         {
+            InitType Type = new InitType();
+            Type.Paths = new FilePaths();
+            Type.ServerProp = new Props();
+
+            Type.initType = initilizeType;
             Message.Write("Advanced Initializing Started", ConsoleMessage.MessageType.BACKPROCESS);
             //Program.Json Exits
-            ProgramJsonPath = ProgramJsonPathArg;
-            if (File.Exists(ProgramJsonPath))
+            Type.Paths.ProgramJson = ProgramJsonPathArg;
+            if (File.Exists(Type.Paths.ProgramJson))
             {
                 Message.Write("Program.Json - Ready!",ConsoleMessage.MessageType.SUCCESS);
             }
@@ -55,23 +58,65 @@
             Server.ReceiverTask = ReceiveTask;
             if (StartServer)
             {
-                Server.startListen();
+                Server.Init(Type);
             }
         }

         //Basic Start Initializing
         public Init()
         {
-            Message.Write("Basic Initializing",ConsoleMessage.MessageType.BACKPROCESS);
-            ProgramJsonPath = "Program.json";
+            InitType Type = new InitType();
+            Type.Paths = new FilePaths();
+            Type.ServerProp = new Props();
+            //Information Message
+            Message.Write("Basic Initializing", ConsoleMessage.MessageType.BACKPROCESS);
+
+            //
+            //File Paths Init
+            //
+            Type.Paths.ProgramJson = "Program.json";
+            Type.Paths.MacPermissions = "Permissions/Mac.json";
+            Type.Paths.IpPermissions = "Permissions/Ip.json";
+
+            //
+            //WCF Service Init
+            //
             Host = new ServiceHost(typeof(Services.FuzzyService));
             Host.Open();
             if (Host.State == CommunicationState.Opened)
             {
                 Message.Write("WCF Service is Running", ConsoleMessage.MessageType.BACKPROCESS);
             }
+
+            //
+            //Fuzzy Server Init
+            //
             Server = new FuzzyServer(new IPEndPoint(IPAddress.Any,5959));
-            Server.startListen();
+            Server.Init(Type);
+        }
+
+        public Init(InitType Type)
+        {
+            staticInitData.Current_Init_Type = Type;
+            if (!string.IsNullOrEmpty(Type.FirstConsole_Message))
+            {
+                Console.WriteLine(Type.FirstConsole_Message);
+            }
+            if (Type.Wcf_Running)
+            {
+                Host = new ServiceHost(typeof(Services.FuzzyService));
+                Host.Open();
+                if (Host.State == CommunicationState.Opened)
+                {
+                    Message.Write("WCF Service is Running", ConsoleMessage.MessageType.BACKPROCESS);
+                }
+            }
+            if (Type.Server_Running)
+            {
+                Server = new FuzzyServer(new IPEndPoint(IPAddress.Parse(Type.ServerProp.IP), int.Parse(Type.ServerProp.Port)));
+                Server.Init(Type);
+                Console.WriteLine("Listening : " + Type.ServerProp.IP + ":" + Type.ServerProp.Port);
+            }
         }
     }
 }


Implementing ==

Implementing ==

--- GTPWrapper/DataTypes/Sign.cs
+++ GTPWrapper/DataTypes/Sign.cs
@@ -20,6 +20,14 @@
             this.Value = this.Value == 2 ? -1 : this.Value == -2 ? 1 : this.Value;
         }

+        public override int GetHashCode() {
+            return ((int)this).GetHashCode();
+        }
+
+        public override bool Equals(object obj) {
+            return obj.Equals(this);
+        }
+
         public static Sign operator +(Sign s1, Sign s2) {
             return new Sign(s1.Value + s2.Value);
         }
@@ -30,6 +38,14 @@

         public static Sign operator -(Sign s1, Sign s2) {
             return -s2 + s1;
+        }
+
+        public static bool operator ==(Sign s1, Sign s2) {
+            return (int)s1 == (int)s2;
+        }
+
+        public static bool operator !=(Sign s1, Sign s2) {
+            return (int)s1 != (int)s2;
         }

         public static implicit operator Sign(int value) {


- timer fixed

- timer fixed

--- Gameplay/TimedDeactivator.cs
+++ Gameplay/TimedDeactivator.cs
@@ -13,7 +13,7 @@
             gameObject.SetActive(false);
         }

-		void Start() {
+		private void OnEnable() {
 			StartCoroutine(Deactivate(Delay));
 		}
 	}


Expose TryParseChangesetId for testability

--- GitTfs/Core/GitRepository.cs
+++ GitTfs/Core/GitRepository.cs
@@ -497,7 +497,20 @@
             return commit.Sha;
         }

-        private readonly Regex tfsIdRegex = new Regex("^git-tfs-id: .*;C([0-9]+)$", RegexOptions.Singleline | RegexOptions.Compiled);
+        private static readonly Regex tfsIdRegex = new Regex("^git-tfs-id: .*;C([0-9]+)$", RegexOptions.Singleline | RegexOptions.Compiled);
+
+        public static bool TryParseChangesetId(string commitMessage, out long changesetId)
+        {
+            var match = tfsIdRegex.Match(commitMessage);
+            if (match.Success)
+            {
+                changesetId = long.Parse(match.Groups[1].Value);
+                return true;
+            }
+
+            changesetId = 0;
+            return false;
+        }

         private Commit FindCommitByChangesetId(long changesetId, string remoteRef = null)
         {
@@ -525,10 +538,9 @@
             Commit commit = null;
             foreach (var c in commitsFromRemoteBranches)
             {
-                var match = tfsIdRegex.Match(c.Message);
-                if (match.Success)
+                long id;
+                if (TryParseChangesetId(c.Message, out id))
                 {
-                    int id = int.Parse(match.Groups[1].Value);
                     changesetsCache[id] = c.Sha;
                     if (id == changesetId)
                     {