add ConfigureAwait when possible

add ConfigureAwait when possible

--- CloudFlareUtilities/ClearanceHandler.cs
+++ CloudFlareUtilities/ClearanceHandler.cs
@@ -1,102 +1,102 @@
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
-using System.Net.Http;
-using System.Net.Http.Headers;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace CloudFlareUtilities
-{
-    /// <summary>
-    /// A HTTP handler that transparently manages Cloudflare's Anti-DDoS measure.
-    /// </summary>
-    /// <remarks>
-    /// Only the JavaScript challenge can be handled. CAPTCHA and IP address blocking cannot be bypassed.
-    /// </remarks>
-    public class ClearanceHandler : DelegatingHandler
-    {
-        /// <summary>
-        /// The default number of retries, if clearance fails.
-        /// </summary>
-        public static readonly int DefaultMaxRetries = 3;
-
-        private static readonly IEnumerable<string> CloudFlareServerNames = new[] { "cloudflare", "cloudflare-nginx" };
-        private const string IdCookieName = "__cfduid";
-        private const string ClearanceCookieName = "cf_clearance";
-
-        private readonly CookieContainer _cookies = new CookieContainer();
-        private readonly HttpClient _client;
-
-        /// <summary>
-        /// Creates a new instance of the <see cref="ClearanceHandler"/> class with a <see cref="HttpClientHandler"/> as inner handler.
-        /// </summary>
-        public ClearanceHandler() : this(new HttpClientHandler()) { }
-
-        /// <summary>
-        /// Creates a new instance of the <see cref="ClearanceHandler"/> class with a specific inner handler.
-        /// </summary>
-        /// <param name="innerHandler">The inner handler which is responsible for processing the HTTP response messages.</param>
-        public ClearanceHandler(HttpMessageHandler innerHandler) : base(innerHandler)
-        {
-            _client = new HttpClient(new HttpClientHandler
-            {
-                AllowAutoRedirect = false,
-                CookieContainer = _cookies
-            });
-        }
-
-        /// <summary>
-        /// Gets or sets the number of clearance retries, if clearance fails.
-        /// </summary>
-        /// <remarks>A negative value causes an infinite amount of retries.</remarks>
-        public int MaxRetries { get; set; } = DefaultMaxRetries;
-
-        private HttpClientHandler ClientHandler => InnerHandler.GetMostInnerHandler() as HttpClientHandler;
-
-        /// <summary>
-        /// Releases the unmanaged resources used by the <see cref="ClearanceHandler"/>, and optionally disposes of the managed resources.
-        /// </summary>
-        /// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to releases only unmanaged resources.</param>
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing)
-                _client.Dispose();
-
-            base.Dispose(disposing);
-        }
-
-        /// <summary>
-        /// Sends an HTTP request to the inner handler to send to the server as an asynchronous operation.
-        /// </summary>
-        /// <param name="request">The HTTP request message to send to the server.</param>
-        /// <param name="cancellationToken">A cancellation token to cancel operation.</param>
-        /// <returns>The task object representing the asynchronous operation.</returns>
-        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
+using System.Collections.Generic;
+using System.Linq;
+using System.Net;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace CloudFlareUtilities
+{
+    /// <summary>
+    /// A HTTP handler that transparently manages Cloudflare's Anti-DDoS measure.
+    /// </summary>
+    /// <remarks>
+    /// Only the JavaScript challenge can be handled. CAPTCHA and IP address blocking cannot be bypassed.
+    /// </remarks>
+    public class ClearanceHandler : DelegatingHandler
+    {
+        /// <summary>
+        /// The default number of retries, if clearance fails.
+        /// </summary>
+        public static readonly int DefaultMaxRetries = 3;
+
+        private static readonly IEnumerable<string> CloudFlareServerNames = new[] { "cloudflare", "cloudflare-nginx" };
+        private const string IdCookieName = "__cfduid";
+        private const string ClearanceCookieName = "cf_clearance";
+
+        private readonly CookieContainer _cookies = new CookieContainer();
+        private readonly HttpClient _client;
+
+        /// <summary>
+        /// Creates a new instance of the <see cref="ClearanceHandler"/> class with a <see cref="HttpClientHandler"/> as inner handler.
+        /// </summary>
+        public ClearanceHandler() : this(new HttpClientHandler()) { }
+
+        /// <summary>
+        /// Creates a new instance of the <see cref="ClearanceHandler"/> class with a specific inner handler.
+        /// </summary>
+        /// <param name="innerHandler">The inner handler which is responsible for processing the HTTP response messages.</param>
+        public ClearanceHandler(HttpMessageHandler innerHandler) : base(innerHandler)
+        {
+            _client = new HttpClient(new HttpClientHandler
+            {
+                AllowAutoRedirect = false,
+                CookieContainer = _cookies
+            });
+        }
+
+        /// <summary>
+        /// Gets or sets the number of clearance retries, if clearance fails.
+        /// </summary>
+        /// <remarks>A negative value causes an infinite amount of retries.</remarks>
+        public int MaxRetries { get; set; } = DefaultMaxRetries;
+
+        private HttpClientHandler ClientHandler => InnerHandler.GetMostInnerHandler() as HttpClientHandler;
+
+        /// <summary>
+        /// Releases the unmanaged resources used by the <see cref="ClearanceHandler"/>, and optionally disposes of the managed resources.
+        /// </summary>
+        /// <param name="disposing"><see langword="true"/> to release both managed and unmanaged resources; <see langword="false"/> to releases only unmanaged resources.</param>
+        protected override void Dispose(bool disposing)
+        {
+            if (disposing)
+                _client.Dispose();
+
+            base.Dispose(disposing);
+        }
+
+        /// <summary>
+        /// Sends an HTTP request to the inner handler to send to the server as an asynchronous operation.
+        /// </summary>
+        /// <param name="request">The HTTP request message to send to the server.</param>
+        /// <param name="cancellationToken">A cancellation token to cancel operation.</param>
+        /// <returns>The task object representing the asynchronous operation.</returns>
+        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
         {
             var IdCookieBefore = ClientHandler.CookieContainer.GetCookiesByName(request.RequestUri, IdCookieName).FirstOrDefault();
             var clearanceCookieBefore = ClientHandler.CookieContainer.GetCookiesByName(request.RequestUri, ClearanceCookieName).FirstOrDefault();

-            EnsureClientHeader(request);
-            InjectCookies(request);
-
-            var response = await base.SendAsync(request, cancellationToken);
-
-            // (Re)try clearance if required.
-            var retries = 0;
-            while (IsClearanceRequired(response) && (MaxRetries < 0 || retries <= MaxRetries))
-            {
-                cancellationToken.ThrowIfCancellationRequested();
-
-                await PassClearance(response, cancellationToken);
-                InjectCookies(request);
-                response = await base.SendAsync(request, cancellationToken);
-
-                retries++;
-            }
-
-            // Clearance failed.
-            if (IsClearanceRequired(response))
+            EnsureClientHeader(request);
+            InjectCookies(request);
+
+            var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
+
+            // (Re)try clearance if required.
+            var retries = 0;
+            while (IsClearanceRequired(response) && (MaxRetries < 0 || retries <= MaxRetries))
+            {
+                cancellationToken.ThrowIfCancellationRequested();
+
+                await PassClearance(response, cancellationToken).ConfigureAwait(false);
+                InjectCookies(request);
+                response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
+
+                retries++;
+            }
+
+            // Clearance failed.
+            if (IsClearanceRequired(response))
                 throw new CloudFlareClearanceException(retries);

             var IdCookieAfter = ClientHandler.CookieContainer.GetCookiesByName(request.RequestUri, IdCookieName).FirstOrDefault();
@@ -112,79 +112,79 @@
                 response.Headers.Add(HttpHeader.SetCookie, clearanceCookieAfter.ToHeaderValue());
             }

-            return response;
-        }
-
-        private static void EnsureClientHeader(HttpRequestMessage request)
-        {
-            if (!request.Headers.UserAgent.Any())
-                request.Headers.UserAgent.Add(new ProductInfoHeaderValue("Client", "1.0"));
-        }
-
-        private static bool IsClearanceRequired(HttpResponseMessage response)
-        {
-            var isServiceUnavailable = response.StatusCode == HttpStatusCode.ServiceUnavailable;
+            return response;
+        }
+
+        private static void EnsureClientHeader(HttpRequestMessage request)
+        {
+            if (!request.Headers.UserAgent.Any())
+                request.Headers.UserAgent.Add(new ProductInfoHeaderValue("Client", "1.0"));
+        }
+
+        private static bool IsClearanceRequired(HttpResponseMessage response)
+        {
+            var isServiceUnavailable = response.StatusCode == HttpStatusCode.ServiceUnavailable;
             var isCloudFlareServer = response.Headers.Server
                 .Any(i => i.Product != null && CloudFlareServerNames.Any(s => string.Compare(s, i.Product.Name, System.StringComparison.OrdinalIgnoreCase) == 0));
-
-            return isServiceUnavailable && isCloudFlareServer;
-        }
-
-        private void InjectCookies(HttpRequestMessage request)
-        {
-            var cookies = _cookies.GetCookies(request.RequestUri).Cast<Cookie>().ToList();
-            var idCookie = cookies.FirstOrDefault(c => c.Name == IdCookieName);
-            var clearanceCookie = cookies.FirstOrDefault(c => c.Name == ClearanceCookieName);
-
-            if (idCookie == null || clearanceCookie == null)
-                return;
-
-            if (ClientHandler.UseCookies)
-            {
-                ClientHandler.CookieContainer.Add(request.RequestUri, idCookie);
-                ClientHandler.CookieContainer.Add(request.RequestUri, clearanceCookie);
-            }
-            else
-            {
-                request.Headers.Add(HttpHeader.Cookie, idCookie.ToHeaderValue());
-                request.Headers.Add(HttpHeader.Cookie, clearanceCookie.ToHeaderValue());
-            }
-        }
-
-        private async Task PassClearance(HttpResponseMessage response, CancellationToken cancellationToken)
-        {
-            SaveIdCookie(response);
-
-            var pageContent = await response.Content.ReadAsStringAsync();
-            var scheme = response.RequestMessage.RequestUri.Scheme;
-            var host = response.RequestMessage.RequestUri.Host;
-            var port = response.RequestMessage.RequestUri.Port;
-            var solution = ChallengeSolver.Solve(pageContent, host);
-
-            var clearanceUri = $"{scheme}://{host}:{port}{solution.ClearanceQuery}";
-
-            await Task.Delay(5000, cancellationToken);
-
-            var clearanceRequest = new HttpRequestMessage(HttpMethod.Get, clearanceUri);
-
-            IEnumerable<string> userAgent;
-            if (response.RequestMessage.Headers.TryGetValues(HttpHeader.UserAgent, out userAgent))
-                clearanceRequest.Headers.Add(HttpHeader.UserAgent, userAgent);
-
-            var passResponse = await _client.SendAsync(clearanceRequest, cancellationToken);
-            SaveIdCookie(passResponse); // new ID might be set as a response to the challenge in some cases
-        }
-
-        private void SaveIdCookie(HttpResponseMessage response)
-        {
-            var cookies = response.Headers
-                .Where(pair => pair.Key == HttpHeader.SetCookie)
-                .SelectMany(pair => pair.Value)
-                .Where(cookie => cookie.StartsWith($"{IdCookieName}="));
-
-            if (cookies.Count() == 0)
-                return;
-
+
+            return isServiceUnavailable && isCloudFlareServer;
+        }
+
+        private void InjectCookies(HttpRequestMessage request)
+        {
+            var cookies = _cookies.GetCookies(request.RequestUri).Cast<Cookie>().ToList();
+            var idCookie = cookies.FirstOrDefault(c => c.Name == IdCookieName);
+            var clearanceCookie = cookies.FirstOrDefault(c => c.Name == ClearanceCookieName);
+
+            if (idCookie == null || clearanceCookie == null)
+                return;
+
+            if (ClientHandler.UseCookies)
+            {
+                ClientHandler.CookieContainer.Add(request.RequestUri, idCookie);
+                ClientHandler.CookieContainer.Add(request.RequestUri, clearanceCookie);
+            }
+            else
+            {
+                request.Headers.Add(HttpHeader.Cookie, idCookie.ToHeaderValue());
+                request.Headers.Add(HttpHeader.Cookie, clearanceCookie.ToHeaderValue());
+            }
+        }
+
+        private async Task PassClearance(HttpResponseMessage response, CancellationToken cancellationToken)
+        {
+            SaveIdCookie(response);
+
+            var pageContent = await response.Content.ReadAsStringAsync();
+            var scheme = response.RequestMessage.RequestUri.Scheme;
+            var host = response.RequestMessage.RequestUri.Host;
+            var port = response.RequestMessage.RequestUri.Port;
+            var solution = ChallengeSolver.Solve(pageContent, host);
+
+            var clearanceUri = $"{scheme}://{host}:{port}{solution.ClearanceQuery}";
+
+            await Task.Delay(5000, cancellationToken).ConfigureAwait(false);
+
+            var clearanceRequest = new HttpRequestMessage(HttpMethod.Get, clearanceUri);
+
+            IEnumerable<string> userAgent;
+            if (response.RequestMessage.Headers.TryGetValues(HttpHeader.UserAgent, out userAgent))
+                clearanceRequest.Headers.Add(HttpHeader.UserAgent, userAgent);
+
+            var passResponse = await _client.SendAsync(clearanceRequest, cancellationToken).ConfigureAwait(false);
+            SaveIdCookie(passResponse); // new ID might be set as a response to the challenge in some cases
+        }
+
+        private void SaveIdCookie(HttpResponseMessage response)
+        {
+            var cookies = response.Headers
+                .Where(pair => pair.Key == HttpHeader.SetCookie)
+                .SelectMany(pair => pair.Value)
+                .Where(cookie => cookie.StartsWith($"{IdCookieName}="));
+
+            if (cookies.Count() == 0)
+                return;
+
             // Expire any old cloudflare cookies.
             // If e.g.the cookie domain / path changed we'll have duplicate cookies (breaking the clearance) in some cases
             var oldCookies = ClientHandler.CookieContainer.GetCookies(response.RequestMessage.RequestUri);
@@ -192,10 +192,10 @@
             {
                 if (oldCookie.Name == IdCookieName || oldCookie.Name == ClearanceCookieName)
                     oldCookie.Expired = true;
-            }
-
-            foreach (var cookie in cookies)
-                _cookies.SetCookies(response.RequestMessage.RequestUri, cookie);
-        }
-    }
-}+            }
+
+            foreach (var cookie in cookies)
+                _cookies.SetCookies(response.RequestMessage.RequestUri, cookie);
+        }
+    }
+}


Update Edit.cshtml

Update Edit.cshtml

--- CodeComb.Web/Views/Solution/Edit.cshtml
+++ CodeComb.Web/Views/Solution/Edit.cshtml
@@ -8,7 +8,7 @@

-
+

编辑解题报告 - @Model.Problem.Title

@@ -47,4 +47,4 @@

-
+


update event end wording

update event end wording

--- CompatBot/Commands/EventsBaseCommand.cs
+++ CompatBot/Commands/EventsBaseCommand.cs
@@ -89,7 +89,7 @@
                 var lastNamedEvent = await db.EventSchedule.OrderByDescending(e => e.End).FirstOrDefaultAsync(e => e.Year == current.Year && e.EventName == eventName).ConfigureAwait(false);
                 if (lastNamedEvent.End <= currentTicks)
                 {
-                    var e3EndedMsg = $"__{eventName} {current.Year} has ended. See you next year!__";
+                    var e3EndedMsg = $"__{eventName} {current.Year} has concluded. See you next year!__";
                     if (!string.IsNullOrEmpty(promo))
                         e3EndedMsg += promo;
                     await ctx.RespondAsync(e3EndedMsg).ConfigureAwait(false);


Fix RCDs on space somewhat - space-wizards/space-station-14#4742 compatibility edition (#4878)

--- Content.Server/RCD/Systems/RCDSystem.cs
+++ Content.Server/RCD/Systems/RCDSystem.cs
@@ -64,16 +64,25 @@
                 return;

             // FIXME: Make this work properly. Right now it relies on the click location being on a grid, which is bad.
-            if (!args.ClickLocation.IsValid(EntityManager))
-                return;
-
-            var gridID = args.ClickLocation.GetGridId(EntityManager);
+            var clickLocationMod = args.ClickLocation;
+            // Initial validity check
+            if (!clickLocationMod.IsValid(EntityManager))
+                return;
+            // Try to fix it (i.e. if clicking on space)
+            // Note: Ideally there'd be a better way, but there isn't right now.
+            var gridID = clickLocationMod.GetGridId(EntityManager);
             if (!gridID.IsValid())
+            {
+                clickLocationMod = clickLocationMod.AlignWithClosestGridTile();
+                gridID = clickLocationMod.GetGridId(EntityManager);
+            }
+            // Check if fixing it failed / get final grid ID
+            if (!gridID.IsValid())
                 return;

             var mapGrid = _mapManager.GetGrid(gridID);
-            var tile = mapGrid.GetTileRef(args.ClickLocation);
-            var snapPos = mapGrid.TileIndicesFor(args.ClickLocation);
+            var tile = mapGrid.GetTileRef(clickLocationMod);
+            var snapPos = mapGrid.TileIndicesFor(clickLocationMod);

             //No changing mode mid-RCD
             var startingMode = rcd.Mode;
@@ -99,7 +108,7 @@
             {
                 //Floor mode just needs the tile to be a space tile (subFloor)
                 case RcdMode.Floors:
-                    mapGrid.SetTile(args.ClickLocation, new Tile(_tileDefinitionManager["floor_steel"].TileId));
+                    mapGrid.SetTile(clickLocationMod, new Tile(_tileDefinitionManager["floor_steel"].TileId));
                     break;
                 //We don't want to place a space tile on something that's already a space tile. Let's do the inverse of the last check.
                 case RcdMode.Deconstruct:


Fixed section resetting bug

Fixed section resetting bug

--- Core6502DotNet/src/Core/BinaryOutput.cs
+++ Core6502DotNet/src/Core/BinaryOutput.cs
@@ -270,6 +270,8 @@
                 throw new ProgramOverflowException($"Program overflowed {size} bytes.");
             ProgramCounter += size;
             LogicalPC += size;
+            if (_sectionCollection.SectionSelected)
+                _sectionCollection.SetOutputCount(_pc - _sectionCollection.SelectedStartAddress);
         }

         /// <summary>
@@ -354,8 +356,7 @@
         public void Align(int amount)
         {
             var align = GetAlignmentSize(LogicalPC, amount);
-            LogicalPC += align;
-            ProgramCounter += align;
+            AddUninitialized(align);
         }

         /// <summary>


+Tutorial Skipping +Free Research

+Tutorial Skipping
+Free Research

--- CreativeSurvivalEvolved/Bootstrapper.cs
+++ CreativeSurvivalEvolved/Bootstrapper.cs
@@ -6,30 +6,25 @@
 using System.Collections.Generic;
 using UnityEngine;

-#if DEBUG
-using UnityEngine;
-#endif
-
 namespace CreativeSurvivalEvolved
 {
 	public class Bootstrapper : FortressCraftMod
 	{
 		private Ini _settings;
-		private Boolean _registered;

 		private List<string> _recipes;
 		private List<CraftData> _newRecipes;

+		private Boolean _registered;
 		private Boolean _recipesChanged;
 		private Boolean _itemsChanged;
 		private Boolean _terrainChanged;
+		private Boolean _researchChanged;

 		private void Update()
 		{
 			if (!this._registered)
-			{
 				return;
-			}

 			if (!this._recipesChanged)
 				this.ModifyRecipes();
@@ -42,6 +37,12 @@

 			if (this._recipes != null && this._terrainChanged && this._itemsChanged && this._recipesChanged)
 				this.ApplyRecipes();
+
+			if (!this._researchChanged && ResearchDataEntry.mEntries != null)
+				this.ModifyResearch();
+
+			if (SurvivalPlayerScript.meTutorialState != SurvivalPlayerScript.eTutorialState.NowFuckOff)
+				this.ProgressTutorial();
 		}

 		private void ModifyRecipes()
@@ -55,9 +56,6 @@

 				foreach (var recipe in recipeSet.Value)
 				{
-					if (recipe.Key == "Snow" || recipe.Key == "arther core")
-						continue;
-
 					recipe.Costs.Clear();
 					recipe.CraftTime = 0;
 					recipe.ResearchCost = 0;
@@ -165,6 +163,53 @@
 			this._recipes = null;
 		}

+		private void ModifyResearch()
+		{
+			var researches = 0;
+			foreach (var entry in ResearchDataEntry.mEntries)
+			{
+				var keyEntry = ResearchDataEntry.mEntriesByKey?[entry.Key];
+
+				if (keyEntry != null)
+				{
+					keyEntry.ResearchCost = 0;
+
+					keyEntry.ResearchRequirements?.Clear();
+					keyEntry.ProjectItemRequirements?.Clear();
+					keyEntry.ScanRequirements?.Clear();
+				}
+
+				entry.ResearchCost = 0;
+
+				entry.ResearchRequirements?.Clear();
+				entry.ProjectItemRequirements?.Clear();
+				entry.ScanRequirements?.Clear();
+
+				researches++;
+			}
+
+			this._researchChanged = true;
+
+#if DEBUG
+			Debug.LogError($"{researches} Research Projects now are free to research!");
+#endif
+		}
+
+		private void ProgressTutorial()
+		{
+			var state = (Int32)SurvivalPlayerScript.meTutorialState;
+			if (state >= 2)
+				SurvivalPlayerScript.meTutorialState++;
+
+			switch ((SurvivalPlayerScript.eTutorialState) state)
+			{
+				case SurvivalPlayerScript.eTutorialState.CraftSomething:
+					WorldScript.mLocalPlayer.mInventory.AddItem(ItemManager.SpawnItem(2000)); // Give the player an Arther Power Core
+					break;
+			}
+
+		}
+
 		private CraftData[] CreateRecipe(ItemEntry item)
 		{
 			if (string.IsNullOrEmpty(item.Sprite))


workaround proxy cached hashes causing invalid checksum during update.

--- DamageMeter.AutoUpdate/UpdateManager.cs
+++ DamageMeter.AutoUpdate/UpdateManager.cs
@@ -185,7 +185,7 @@
         {
             using (var client = new WebClient())
             {
-                var compressed = await client.OpenReadTaskAsync(new Uri("http://diclah.com/~yukikoo/ShinraMeterV.sha1.zip")).ConfigureAwait(false);
+                var compressed = await client.OpenReadTaskAsync(new Uri("http://diclah.com/~yukikoo/ShinraMeterV.sha1.zip?seed="+DateTime.UtcNow.Ticks)).ConfigureAwait(false);
                 if (compressed == null) { return true; }
                 using (var stream = new MemoryStream())
                 {


fix S_WHISPER

fix S_WHISPER

--- DamageMeter.Core/Heuristic/S_WHISPER.cs
+++ DamageMeter.Core/Heuristic/S_WHISPER.cs
@@ -91,7 +91,7 @@
                 return;
             }

-            if (Reader.BaseStream.Position + 2 != Reader.BaseStream.Length) //at this point, we must have reached the end of the stream
+            if (Reader.BaseStream.Position != Reader.BaseStream.Length) //at this point, we must have reached the end of the stream
             {
                 return;
             }


bug fix

bug fix

--- Debugger/ImprovedWorkshopIntegration.cs
+++ Debugger/ImprovedWorkshopIntegration.cs
@@ -75,7 +75,6 @@
                 return;
             }

-
             var go = GameObject.Find("(Library) WorkshopModUploadPanel");
             if (go == null)
             {
@@ -305,11 +304,16 @@
                     BindingFlags.Instance | BindingFlags.NonPublic), revertState3);
             }

-            var customContentPanel = GameObject.Find("(Library) CustomContentPanel").GetComponent<CustomContentPanel>();
-
-            typeof (CustomContentPanel).GetMethod("RefreshPlugins",
-                BindingFlags.Instance | BindingFlags.NonPublic)
-                .Invoke(customContentPanel, null);
+            if (GameObject.Find("(Library) CustomContentPanel") != null)
+            {
+                var customContentPanel = GameObject.Find("(Library) CustomContentPanel").GetComponent<CustomContentPanel>();
+                if (customContentPanel != null)
+                {
+                    typeof(CustomContentPanel).GetMethod("RefreshPlugins",
+                        BindingFlags.Instance | BindingFlags.NonPublic)
+                        .Invoke(customContentPanel, null);
+                }
+            }

             bootstrapped = false;
         }


Improved performance by removing unnecessary code.

--- DemoInfo/DP/Handler/GameEventHandler.cs
+++ DemoInfo/DP/Handler/GameEventHandler.cs
@@ -41,9 +41,6 @@
 			if (eventDescriptor.name == "round_announce_match_start")
 				parser.RaiseMatchStarted();

-			foreach (var d in rawEvent.keys) {
-				GetData (d);
-			}

 			Dictionary<string, object> data;
 			switch (eventDescriptor.name) {


RigidBody Tweaks #CHANGE: Changed RigidBody Raycasts API slightly to promote more performant usage. #CHANGE: RayCastData is now a struct to reduce heap memory allocations.

--- Duality/Components/Physics/RigidBody.cs
+++ Duality/Components/Physics/RigidBody.cs
@@ -1212,23 +1212,92 @@
 			// Make sure to re-initialize the targets body, if it was shut down
 			if (wasInitialized) target.Initialize();
 		}
-
+
 		/// <summary>
 		/// Performs a 2d physical raycast in world coordinates.
 		/// </summary>
-		/// <param name="worldCoordA">The starting point.</param>
-		/// <param name="worldCoordB">The desired end point.</param>
+		/// <param name="start">The starting point in world coordinates.</param>
+		/// <param name="end">The desired end point in world coordinates.</param>
 		/// <param name="callback">
 		/// The callback that is invoked for each hit on the raycast. Note that the order in which each hit occurs isn't deterministic
 		/// and may appear random. Return -1 to ignore the curret shape, 0 to terminate the raycast, data.Fraction to clip the ray for current hit, or 1 to continue.
 		/// </param>
-		/// <returns>Returns a list of all occurred hits, ordered by their Fraction value.</returns>
-		public static List<RayCastData> RayCast(Vector2 worldCoordA, Vector2 worldCoordB, RayCastCallback callback = null)
+		public static void RayCast(Vector2 start, Vector2 end, RayCastCallback callback)
 		{
 			if (callback == null) callback = Raycast_DefaultCallback;
-			Vector2 fsWorldCoordA = PhysicsUnit.LengthToPhysical * worldCoordA;
-			Vector2 fsWorldCoordB = PhysicsUnit.LengthToPhysical * worldCoordB;
-			List<RayCastData> hitData = new List<RayCastData>();
+
+			Vector2 fsWorldCoordA = PhysicsUnit.LengthToPhysical * start;
+			Vector2 fsWorldCoordB = PhysicsUnit.LengthToPhysical * end;
+
+			Scene.PhysicsWorld.RayCast(delegate(Fixture fixture, Vector2 pos, Vector2 normal, float fraction)
+			{
+				return callback(new RayCastData(
+					fixture.UserData as ShapeInfo,
+					PhysicsUnit.LengthToDuality * pos,
+					normal,
+					fraction));
+			}, fsWorldCoordA, fsWorldCoordB);
+		}
+		/// <summary>
+		/// Performs a 2d physical raycast in world coordinates.
+		/// </summary>
+		/// <param name="start">The starting point in world coordinates.</param>
+		/// <param name="end">The desired end point in world coordinates.</param>
+		/// <param name="callback">
+		/// The callback that is invoked for each hit on the raycast. Note that the order in which each hit occurs isn't deterministic
+		/// and may appear random. Return -1 to ignore the curret shape, 0 to terminate the raycast, data.Fraction to clip the ray for current hit, or 1 to continue.
+		/// </param>
+		/// <param name="hits">Returns a list of all occurred hits, ordered by their Fraction value.</param>
+		public static void RayCast(Vector2 start, Vector2 end, RayCastCallback callback, out RawList<RayCastData> hits)
+		{
+			if (callback == null) callback = Raycast_DefaultCallback;
+
+			Vector2 fsWorldCoordA = PhysicsUnit.LengthToPhysical * start;
+			Vector2 fsWorldCoordB = PhysicsUnit.LengthToPhysical * end;
+
+			RawList<RayCastData> localHits = new RawList<RayCastData>();
+			Scene.PhysicsWorld.RayCast(delegate(Fixture fixture, Vector2 pos, Vector2 normal, float fraction)
+			{
+				int oldCount = localHits.Count++;
+				RayCastData[] data = localHits.Data;
+
+				data[oldCount] = new RayCastData(
+					fixture.UserData as ShapeInfo,
+					PhysicsUnit.LengthToDuality * pos,
+					normal,
+					fraction);
+
+				float result = callback(data[oldCount]);
+				if (result < 0.0f)
+					localHits.Count--;
+
+				return result;
+			}, fsWorldCoordA, fsWorldCoordB);
+			localHits.Data.StableSort(0, localHits.Count, (d1, d2) => (int)(1000000.0f * (d1.Fraction - d2.Fraction)));
+
+			hits = localHits;
+		}
+		/// <summary>
+		/// Performs a 2d physical raycast in world coordinates.
+		/// </summary>
+		/// <param name="start">The starting point in world coordinates.</param>
+		/// <param name="end">The desired end point in world coordinates.</param>
+		/// <param name="callback">
+		/// The callback that is invoked for each hit on the raycast. Note that the order in which each hit occurs isn't deterministic
+		/// and may appear random. Return -1 to ignore the curret shape, 0 to terminate the raycast, data.Fraction to clip the ray for current hit, or 1 to continue.
+		/// </param>
+		/// <param name="firstHit">Returns the first hit that occurs, i.e. the one with the highest proximity to the starting point.</param>
+		/// <returns>Returns whether anything has been hit.</returns>
+		public static bool RayCast(Vector2 start, Vector2 end, RayCastCallback callback, out RayCastData firstHit)
+		{
+			if (callback == null) callback = Raycast_DefaultCallback;
+
+			Vector2 fsWorldCoordA = PhysicsUnit.LengthToPhysical * start;
+			Vector2 fsWorldCoordB = PhysicsUnit.LengthToPhysical * end;
+
+			float firstHitFraction = float.MaxValue;
+			RayCastData firstHitLocal = default(RayCastData);
+
 			Scene.PhysicsWorld.RayCast(delegate(Fixture fixture, Vector2 pos, Vector2 normal, float fraction)
 			{
 				RayCastData data = new RayCastData(
@@ -1236,17 +1305,25 @@
 					PhysicsUnit.LengthToDuality * pos,
 					normal,
 					fraction);
+
 				float result = callback(data);
-				if (result >= 0.0f) hitData.Add(data);
+				if (result >= 0.0f && data.Fraction < firstHitFraction)
+				{
+					firstHitLocal = data;
+					firstHitFraction = data.Fraction;
+				}
+
 				return result;
 			}, fsWorldCoordA, fsWorldCoordB);
-			hitData.StableSort((d1, d2) => (int)(1000000.0f * (d1.Fraction - d2.Fraction)));
-			return hitData;
+
+			firstHit = firstHitLocal;
+			return firstHitFraction != float.MaxValue;
 		}
 		private static float Raycast_DefaultCallback(RayCastData data)
 		{
 			return 1.0f;
 		}
+
 		/// <summary>
 		/// Performs a global physical picking operation and returns the <see cref="ShapeInfo">shape</see> in which
 		/// the specified world coordinate is located in.
@@ -1364,7 +1441,7 @@
 	/// <summary>
 	///  Provides data about a <see cref="RigidBody.RayCast"/>.
 	/// </summary>
-	public class RayCastData
+	public struct RayCastData
 	{
 		private ShapeInfo	shape;
 		private Vector2		pos;


3.0.9


[Rust] Fix command usage message for 'lang'

--- Games/Unity/Oxide.Game.Rust/RustCore.cs
+++ Games/Unity/Oxide.Game.Rust/RustCore.cs
@@ -44,6 +44,7 @@
         private readonly Lang lang = Interface.Oxide.GetLibrary<Lang>();
         private readonly Dictionary<string, string> messages = new Dictionary<string, string>
         {
+            {"CommandUsageLang", "Usage: lang <two-digit language code"},
             {"CommandUsageLoad", "Usage: load *|<pluginname>+"},
             {"CommandUsageGrant", "Usage: grant <group|user> <name|id> <permission>"},
             {"CommandUsageGroup", "Usage: group <add|remove|set> <name> [title] [rank]"},
@@ -769,7 +770,7 @@
         {
             if (args.Length < 1)
             {
-                player.Reply(lang.GetMessage("CommandUsageGroup", this, player.Id));
+                player.Reply(lang.GetMessage("CommandUsageLang", this, player.Id));
                 return;
             }


(Correction) Changed to using REST API

(Correction) Changed to using REST API

- As per discussion here:
	https://github.com/Particular/GitVersion/pull/262
- Changed to use the AppVeyor REST API SetVariable method, instead of setting an Environment Variable

--- GitVersionCore/BuildServers/AppVeyor.cs
+++ GitVersionCore/BuildServers/AppVeyor.cs
@@ -61,11 +61,19 @@

         public override string[] GenerateSetParameterMessage(string name, string value)
         {
-            Environment.SetEnvironmentVariable("GitVersion." + name, value);
+            using (var wc = new WebClient())
+            {
+                wc.BaseAddress = Environment.GetEnvironmentVariable("APPVEYOR_API_URL");
+                wc.Headers["Accept"] = "application/json";
+                wc.Headers["Content-type"] = "application/json";
+
+                var body = string.Format("{{ \"name\": \"GitVersion_{0}\", \"value\": \"{1}\" }}", name, value);
+                wc.UploadData("api/build/variables", "POST", Encoding.UTF8.GetBytes(body));
+            }

             return new[]
             {
-                string.Format("Adding Environment Variable. name='GitVersion.{0}' value='{1}']", name, value)
+                string.Format("Adding Environment Variable. name='GitVersion_{0}' value='{1}']", name, value)
             };
         }
     }


Avoid a strange situation when a subscription client comes to null. Really, Is not a normal situation, but I have noticed that sometimes, a subscription client could be null. In these cases, an exception is generated at runtime. Here, we mitigate this behaviour.

--- GnatMQ/Managers/MqttPublisherManager.cs
+++ GnatMQ/Managers/MqttPublisherManager.cs
@@ -292,8 +292,11 @@
                                 {
                                     qosLevel = (subscription.QosLevel < publish.QosLevel) ? subscription.QosLevel : publish.QosLevel;

-                                    // send PUBLISH message to the current subscriber
-                                    subscription.Client.Publish(publish.Topic, publish.Message, qosLevel, publish.Retain);
+                                    if (subscription.Client != null)
+                                    {
+                                        // send PUBLISH message to the current subscriber
+                                        subscription.Client.Publish(publish.Topic, publish.Message, qosLevel, publish.Retain);
+                                    }
                                 }
                             }


Remove redundant else statements in Server.cs

--- Server.cs
+++ Server.cs
@@ -366,17 +366,11 @@
                         {
                             break;
                         }
-                        else
-                        {
-                            _logger.Info("Validation of mods failed");
-                            return false;
-                        }
-                    }
-                    else
-                    {
                         _logger.Info("Validation of mods failed");
                         return false;
                     }
+                    _logger.Info("Validation of mods failed");
+                    return false;
                 }
             }
             _logger.Info("Validation of mods passed");


Add GetChangedFiles, Zsync "make" is now on ran on changed files. Refs T14

--- Server.cs
+++ Server.cs
@@ -52,6 +52,7 @@
         List<ModFolderHash> _modHashes;
         Guid _serverGuid;
         List<Uri> _syncUris;
+        private List<ModFolderHash> _oldHashes;

         public bool LoadFromWeb(Uri remoteServerFile, DirectoryInfo localPath)
         {
@@ -193,17 +194,68 @@
         {
             _lastUpdate = DateTime.Now;
             _mods = GetFolders(inputDirectory);
+            _oldHashes = HashAllMods;
             FileWriter.WriteServerConfig(GetServerFile(), new FileInfo(Path.Combine(inputDirectory.FullName, "server.json")));
             FileCopy.CopyAll(inputDirectory, new DirectoryInfo(_localPath));
             FileCopy.CleanUpFolder(inputDirectory, new DirectoryInfo(_localPath), new DirectoryInfo(_localPath));
             // TODO: Maybe remove all zsync files?
             _modHashes = HashAllMods;
-            foreach (string f in Directory.EnumerateFiles(_localPath, "*", SearchOption.AllDirectories).Where(name => !name.EndsWith(".zsync")))
+
+            List<String> changedFiles = GetChangedFiles(inputDirectory);
+
+            foreach (string f in changedFiles)
             {
                 ZsyncManager.Make(f);
             }
             FileWriter.WriteModHashes(_modHashes, new DirectoryInfo(_localPath));

+        }
+        /// <summary>
+        /// Compares files in the input directory with the hashes of the old files, creating a list of those that have changed
+        /// </summary>
+        /// <param name="inputDirectory">Mod input directory</param>
+        /// <returns>List of changed files</returns>
+        private List<string> GetChangedFiles(DirectoryInfo inputDirectory)
+        {
+            var changedFiles = new List<string>();
+
+            foreach (string f in Directory.EnumerateFiles(_localPath, "*", SearchOption.AllDirectories)
+                .Where(name => !name.EndsWith(".zsync") && !name.EndsWith("hash.json") &&
+                               !name.EndsWith("server.json")))
+            {
+                // Find the source file in the hashes and compare
+                string path = f.Replace(_localPath, string.Empty).TrimStart(Path.DirectorySeparatorChar);
+
+
+                string[] splitPath = path.Split(new[] {Path.DirectorySeparatorChar}, 2);
+
+                string mod = splitPath[0];
+                string relativePath = splitPath[1];
+
+                List<HashType> oldModHash = _oldHashes.FirstOrDefault(x => x.ModName.ModName == mod).Hashes;
+
+                HashType hash1 =
+                    oldModHash.FirstOrDefault(x => x.FileName.TrimStart(Path.DirectorySeparatorChar) == relativePath);
+
+                List<HashType> newModHash = _modHashes.FirstOrDefault(x => x.ModName.ModName == mod).Hashes;
+
+                HashType hash2 =
+                    newModHash.FirstOrDefault(x => x.FileName.TrimStart(Path.DirectorySeparatorChar) == relativePath);
+
+                if (hash1 == null || hash2 == null)
+                {
+                    // File is new
+                    changedFiles.Add(f);
+                    break;
+                }
+
+                if (!hash1.Hash.SequenceEqual(hash2.Hash))
+                {
+                    changedFiles.Add(f);
+                }
+            }
+
+            return changedFiles;
         }
         /// <summary>
         /// Returns a list of all the mods this server is aware of


Don't run the marshaler tests for now

Don't run the marshaler tests for now

--- iMobileDevice.Tests/NativeStringArrayMarshalerTests.cs
+++ iMobileDevice.Tests/NativeStringArrayMarshalerTests.cs
@@ -8,7 +8,7 @@
 {
     public class NativeStringArrayMarshalerTests
     {
-        [Fact]
+        [Fact (Skip = "This test should run in its own context")]
         public void TestRoundTrip()
         {
             NativeLibraries.Load();


Add and reorder ZmqSocket contract checks.

--- src/proj/ZeroMQ/Sockets/ZmqSocket.cs
+++ src/proj/ZeroMQ/Sockets/ZmqSocket.cs
@@ -189,12 +189,17 @@
         /// <include file='..\CommonDoc.xml' path='ZeroMQ/Members[@name="Bind"]/*'/>
         public void Bind(string endpoint)
         {
+            this.EnsureNotDisposed();
+
             if (endpoint == null)
             {
                 throw new ArgumentNullException("endpoint");
             }

-            this.EnsureNotDisposed();
+            if (endpoint == string.Empty)
+            {
+                throw new ArgumentException("Unable to Bind to an empty endpoint.", "endpoint");
+            }

             this.HandleProxyResult(this.proxy.Bind(endpoint));
         }
@@ -202,12 +207,17 @@
         /// <include file='..\CommonDoc.xml' path='ZeroMQ/Members[@name="Connect"]/*'/>
         public void Connect(string endpoint)
         {
+            this.EnsureNotDisposed();
+
             if (endpoint == null)
             {
                 throw new ArgumentNullException("endpoint");
             }

-            this.EnsureNotDisposed();
+            if (endpoint == string.Empty)
+            {
+                throw new ArgumentException("Unable to Connect to an empty endpoint.", "endpoint");
+            }

             this.HandleProxyResult(this.proxy.Connect(endpoint));
         }
@@ -255,12 +265,12 @@

         internal void SetSocketOption(SocketOption option, byte[] value)
         {
+            this.EnsureNotDisposed();
+
             if (value == null)
             {
                 throw new ArgumentNullException("value");
             }
-
-            this.EnsureNotDisposed();

             this.HandleProxyResult(this.proxy.SetSocketOption((int)option, value));
         }
@@ -361,12 +371,12 @@

         internal SendResult Send(byte[] buffer, SocketFlags socketFlags)
         {
+            this.EnsureNotDisposed();
+
             if (buffer == null)
             {
                 throw new ArgumentNullException("buffer");
             }
-
-            this.EnsureNotDisposed();

             int bytesSent = this.proxy.Send((int)socketFlags, buffer);


Real fix for saving empty objects

Real fix for saving empty objects

--- KraxbotOSS/Form1.cs
+++ KraxbotOSS/Form1.cs
@@ -90,65 +90,65 @@
         // Chat settings
         public class Settings
         {
-            internal List<UserInfo> Users;
-
-            internal int Version = 0;
-            internal string ChatName = "NoName";
-            internal SteamID ChatID;
-            internal SteamID InvitedID;
-            internal string InvitedName = "NoName";
-
-            internal string Spam = "Kick";
-            internal string WelcomeMsg = "Welcome";
-            internal string WelcomeEnd = "!";
-            internal SteamID LastPoke;
-            internal string DCKick = "Kick";
-
-            internal bool Cleverbot = false;
-            internal bool Translate = false;
-            internal bool Commands = true;
-
-            internal bool Welcome = true;
-            internal bool Games = true;
-            internal bool Define = true;
-            internal bool Wiki = true;
-            internal bool Search = true;
-            internal bool Weather = true;
-            internal bool Store = true;
-            internal bool Responses = true;
-            internal bool Links = true;
-            internal bool Rules = true;
-            internal bool Poke = true;
-            internal bool AllStates = false;
-            internal bool AllPoke = false;
-            internal bool AutoWelcome = false;
-
-            internal int DCLimit = 5;
-            internal int DelayRandom = 120;
-            internal int DelayDefine = 300;
-            internal int DelayGames = 120;
-            internal int DelayRecents = 120;
-            internal int DelaySearch = 120;
-            internal int DelayYT = 120;
-
-            internal int DCKickLimit = 3;
-            internal int DCBanLimit = 5;
-
-            internal int TimeoutRandom = 0;
-            internal int TimeoutDefine = 0;
-            internal int TimeoutGames = 0;
-            internal int TimeoutRecents = 0;
-            internal int TimeoutSearch = 0;
-            internal int TimeoutYT = 0;
-
-            internal bool CustomEnabled = false;
-            internal bool CustomModOnly = false;
-            internal int CustomDelay = 5;
-            internal string CustomCommand = "!custom";
-            internal string CustomResponse = "Custom response";
-
-            internal string AutokickMode = "None";
-            internal SteamID AutokickUser;
+            public List<UserInfo> Users;
+
+            public int Version = 0;
+            public string ChatName = "NoName";
+            public SteamID ChatID;
+            public SteamID InvitedID;
+            public string InvitedName = "NoName";
+
+            public string Spam = "Kick";
+            public string WelcomeMsg = "Welcome";
+            public string WelcomeEnd = "!";
+            public SteamID LastPoke;
+            public string DCKick = "Kick";
+
+            public bool Cleverbot = false;
+            public bool Translate = false;
+            public bool Commands = true;
+
+            public bool Welcome = true;
+            public bool Games = true;
+            public bool Define = true;
+            public bool Wiki = true;
+            public bool Search = true;
+            public bool Weather = true;
+            public bool Store = true;
+            public bool Responses = true;
+            public bool Links = true;
+            public bool Rules = true;
+            public bool Poke = true;
+            public bool AllStates = false;
+            public bool AllPoke = false;
+            public bool AutoWelcome = false;
+
+            public int DCLimit = 5;
+            public int DelayRandom = 120;
+            public int DelayDefine = 300;
+            public int DelayGames = 120;
+            public int DelayRecents = 120;
+            public int DelaySearch = 120;
+            public int DelayYT = 120;
+
+            public int DCKickLimit = 3;
+            public int DCBanLimit = 5;
+
+            public int TimeoutRandom = 0;
+            public int TimeoutDefine = 0;
+            public int TimeoutGames = 0;
+            public int TimeoutRecents = 0;
+            public int TimeoutSearch = 0;
+            public int TimeoutYT = 0;
+
+            public bool CustomEnabled = false;
+            public bool CustomModOnly = false;
+            public int CustomDelay = 5;
+            public string CustomCommand = "!custom";
+            public string CustomResponse = "Custom response";
+
+            public string AutokickMode = "None";
+            public SteamID AutokickUser;
         }

         // User info


Handle invalid links without crashing

Handle invalid links without crashing

--- KraxbotOSS/Form1.cs
+++ KraxbotOSS/Form1.cs
@@ -702,9 +702,14 @@
         string Get(string url)
         {
             // TODO: Check if better way to do this
-            // TODO: Handle invalid links
             using (var client = new System.Net.WebClient())
-                return client.DownloadString(url);
+            {
+                try {
+                    return client.DownloadString(url);
+                } catch (System.Net.WebException e) {
+                    return e.Message;
+                }
+            }
         }

         string EncryptDecrypt(string input, string key)


Let tests wait until track load before testing zoom

--- osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs
+++ osu.Game.Tests/Visual/Editing/TestSceneTimelineZoom.cs
@@ -17,6 +17,8 @@
         {
             double initialVisibleRange = 0;

+            AddUntilStep("wait for load", () => MusicController.TrackLoaded);
+
             AddStep("reset zoom", () => TimelineArea.Timeline.Zoom = 100);
             AddStep("get initial range", () => initialVisibleRange = TimelineArea.Timeline.VisibleRange);

@@ -34,6 +36,8 @@
         {
             double initialVisibleRange = 0;

+            AddUntilStep("wait for load", () => MusicController.TrackLoaded);
+
             AddStep("reset timeline size", () => TimelineArea.Timeline.Width = 1);
             AddStep("get initial range", () => initialVisibleRange = TimelineArea.Timeline.VisibleRange);


Read from stable

Read from stable

--- osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs
+++ osu.Game.Tournament/Screens/Showcase/ShowcaseScreen.cs
@@ -1,11 +1,15 @@
 // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
 // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE

+using System;
+using System.IO;
 using osu.Framework.Allocation;
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
 using osu.Framework.Graphics.Shapes;
+using osu.Framework.Platform.Windows;
 using osu.Game.Beatmaps;
+using osu.Game.Beatmaps.Legacy;
 using osu.Game.Graphics;
 using osu.Game.Graphics.Sprites;
 using osu.Game.Online.API;
@@ -21,7 +25,8 @@
 {
     public class ShowcaseScreen : OsuScreen
     {
-        private readonly Container panelContainer;
+        private Container panel;
+        private readonly Container panelContents;

         [Resolved]
         private APIAccess api { get; set; } = null;
@@ -29,22 +34,78 @@
         [Resolved]
         private RulesetStore rulesets { get; set; } = null;

+        private int lastBeatmapId;
+        private int lastMods;
+
         [BackgroundDependencyLoader]
         private void load()
         {
-            var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = 1091460 });
-            req.Success += success;
-            api.Queue(req);
+            var stable = new StableStorage();
+
+            const string file_ipc_filename = "ipc.txt";
+
+            if (stable.Exists(file_ipc_filename))
+            {
+                Scheduler.AddDelayed(delegate
+                {
+                    try
+                    {
+                        using (var stream = stable.GetStream(file_ipc_filename))
+                        using (var sr = new StreamReader(stream))
+                        {
+                            var beatmapId = int.Parse(sr.ReadLine());
+                            var mods = int.Parse(sr.ReadLine());
+
+                            if (lastBeatmapId == beatmapId)
+                                return;
+
+                            lastMods = mods;
+                            lastBeatmapId = beatmapId;
+
+                            var req = new GetBeatmapRequest(new BeatmapInfo { OnlineBeatmapID = beatmapId });
+                            req.Success += success;
+                            api.Queue(req);
+                        }
+                    }
+                    catch
+                    {
+                        // file might be in use.
+                    }
+                }, 250, true);
+            }
         }

         private void success(APIBeatmap apiBeatmap)
         {
+            panel.FadeInFromZero(300, Easing.OutQuint);
+
             var beatmap = apiBeatmap.ToBeatmap(rulesets);
-            panelContainer.Children = new Drawable[]
-            {
-                new OsuSpriteText
-                {
-                    Text = $"Length {beatmap.OnlineInfo.Length}s",
+
+            var legacyMods = (LegacyMods)lastMods;
+            var bpm = beatmap.BeatmapSet.OnlineInfo.BPM;
+            var length = beatmap.OnlineInfo.Length;
+            string extra = "";
+
+            var ar = beatmap.BaseDifficulty.ApproachRate;
+            if ((legacyMods & LegacyMods.HardRock) > 0)
+            {
+                //ar *= 1.4f;
+                extra = "*";
+            }
+
+            if ((legacyMods & LegacyMods.DoubleTime) > 0)
+            {
+                //ar *= 1.5f;
+                bpm *= 1.5f;
+                length /= 1.5f;
+                extra = "*";
+            }
+
+            panelContents.Children = new Drawable[]
+            {
+                new OsuSpriteText
+                {
+                    Text = $"Length {length}s",
                     Margin = new MarginPadding { Horizontal = 15, Vertical = 5 },
                     Colour = OsuColour.Gray(0.33f),
                     Anchor = Anchor.TopLeft,
@@ -52,7 +113,7 @@
                 },
                 new OsuSpriteText
                 {
-                    Text = $"BPM {beatmap.BeatmapSet.OnlineInfo.BPM:0.#}",
+                    Text = $"BPM {bpm:0.#}",
                     Margin = new MarginPadding { Horizontal = 15, Vertical = 5 },
                     Colour = OsuColour.Gray(0.33f),
                     Anchor = Anchor.BottomLeft,
@@ -60,7 +121,7 @@
                 },
                 new OsuSpriteText
                 {
-                    Text = $"AR {beatmap.BaseDifficulty.ApproachRate:0.#}",
+                    Text = $"AR {ar:0.#}{extra}",
                     Margin = new MarginPadding { Horizontal = 15, Vertical = 5 },
                     Colour = OsuColour.Gray(0.33f),
                     Anchor = Anchor.TopRight,
@@ -68,7 +129,7 @@
                 },
                 new OsuSpriteText
                 {
-                    Text = $"Star Rating {beatmap.StarDifficulty:0.#}",
+                    Text = $"Star Rating {beatmap.StarDifficulty:0.#}{extra}",
                     Margin = new MarginPadding { Horizontal = 15, Vertical = 5 },
                     Colour = OsuColour.Gray(0.33f),
                     Anchor = Anchor.BottomRight,
@@ -95,7 +156,7 @@
                     Anchor = Anchor.BottomCentre,
                     Origin = Anchor.BottomCentre,
                     Y = -10,
-                    Width = 0.9f,
+                    Width = 0.95f,
                     Height = TournamentBeatmapPanel.HEIGHT,
                     CornerRadius = TournamentBeatmapPanel.HEIGHT / 2,
                     Children = new Drawable[]
@@ -105,7 +166,7 @@
                             RelativeSizeAxes = Axes.Both,
                             Colour = OsuColour.Gray(0.93f),
                         },
-                        new Container
+                        panel = new Container
                         {
                             Masking = true,
                             CornerRadius = TournamentBeatmapPanel.HEIGHT / 2,
@@ -120,7 +181,7 @@
                                     RelativeSizeAxes = Axes.Both,
                                     Colour = OsuColour.Gray(0.86f),
                                 },
-                                panelContainer = new Container
+                                panelContents = new Container
                                 {
                                     RelativeSizeAxes = Axes.Both,
                                 }
@@ -139,5 +200,44 @@
                 }
             };
         }
+
+        /// <summary>
+        /// A method of accessing an osu-stable install in a controlled fashion.
+        /// </summary>
+        private class StableStorage : WindowsStorage
+        {
+            protected override string LocateBasePath()
+            {
+                bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs"));
+
+                string stableInstallPath;
+
+                try
+                {
+                    stableInstallPath = "E:\\osu!mappool";
+
+                    if (checkExists(stableInstallPath))
+                        return stableInstallPath;
+                }
+                catch
+                {
+                }
+
+                stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"osu!");
+                if (checkExists(stableInstallPath))
+                    return stableInstallPath;
+
+                stableInstallPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".osu");
+                if (checkExists(stableInstallPath))
+                    return stableInstallPath;
+
+                return null;
+            }
+
+            public StableStorage()
+                : base(string.Empty, null)
+            {
+            }
+        }
     }
 }


delete unused homeController

delete unused homeController

--- HDO2O.API/Controllers/HomeController.cs
+++ HDO2O.API/Controllers/HomeController.cs
@@ -1,18 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Web;
-using System.Web.Mvc;
-
-namespace HDO2O.API.Controllers
-{
-    public class HomeController : Controller
-    {
-        public ActionResult Index()
-        {
-            ViewBag.Title = "Home Page";
-
-            return View();
-        }
-    }
-}


Temp logs to get more info for sql exception.

--- HRI/Controllers/HriSurfaceController.cs
+++ HRI/Controllers/HriSurfaceController.cs
@@ -22,6 +22,8 @@
     /// </summary>
     public class HriSufraceController : SurfaceController
     {
+        static readonly ILog logger = LogManager.GetLogger(typeof(HriSufraceController));
+
         /// <summary>
         /// Build an email message from a template.
         /// </summary>
@@ -258,8 +260,12 @@
             MembershipCreateStatus status;
             Members.RegisterMember(registerModel, out status, registerModel.LoginOnSuccess);

+
+
             if ((string)hriUser["DOB"] != null)
             {
+                logger.Info("Adding role for '" + username + "'");
+                logger.Info(hriUser);
                 Roles.AddUserToRole(username, "Enrolled");
             }


adjusted for Params to be automatically added, reduced overloads for View<>()

--- Ignition.Core/MVC/IgnitionController.cs
+++ Ignition.Core/MVC/IgnitionController.cs
@@ -38,47 +38,42 @@

 		protected ViewResult View<TViewModel>() where TViewModel : BaseViewModel, new()
 		{
-			return View<SimpleAgent<TViewModel>, TViewModel, NullParams>(new NullParams(), null);
-		}
-
-		protected ViewResult View<TViewModel>(object data) where TViewModel : BaseViewModel, new()
-		{
-			return View<SimpleAgent<TViewModel>, TViewModel, NullParams>(new NullParams(), data);
+			return View<SimpleAgent<TViewModel>, TViewModel, NullParams>(null);
 		}

 		protected ViewResult View<TAgent, TViewModel>()
 			where TAgent : Agent<TViewModel>
 			where TViewModel : BaseViewModel, new()
 		{
-			return View<TAgent, TViewModel, NullParams>(new NullParams(), null);
+			return View<TAgent, TViewModel, NullParams>(null);
 		}

-		protected ViewResult View<TAgent, TViewModel, TParams>(TParams param)
-			where TAgent : Agent<TViewModel>
-			where TViewModel : BaseViewModel, new()
-			where TParams : IParamsBase
-		{
-			return View<TAgent, TViewModel, TParams>(param, null);
-		}
-
-		protected ViewResult View<TAgent, TViewModel>(object data)
+		protected ViewResult View<TAgent, TViewModel>(object agentParameters)
 			where TAgent : Agent<TViewModel>
 			where TViewModel : BaseViewModel, new()
 		{
-			return View<TAgent, TViewModel, NullParams>(new NullParams(), data);
+			return View<TAgent, TViewModel, NullParams>(agentParameters);
 		}

-		protected ViewResult View<TAgent, TViewModel, TParams>(TParams parameters, object viewdata)
+	    protected ViewResult View<TAgent, TViewModel, TParams>()
+	        where TAgent : Agent<TViewModel>
+	        where TViewModel : BaseViewModel, new()
+	        where TParams : class, IParamsBase
+	    {
+            return View<TAgent, TViewModel, TParams>(null);
+        }
+
+	    protected ViewResult View<TAgent, TViewModel, TParams>(object agentParameters)
 			where TAgent : Agent<TViewModel>
 			where TViewModel : BaseViewModel, new()
-			where TParams : IParamsBase
+			where TParams : class, IParamsBase
 		{
 			var moduleName = GetType().Name.Replace(GetType().Namespace ?? string.Empty, string.Empty).Replace("Controller", string.Empty);

 		    Context.ContextPage = GetContextItem<IPage>(true, true);
 		    Context.ModuleWrapperName = moduleName;
-		    Context.RenderingParameters = parameters;
-		    Context.AgentParameters = viewdata;
+		    Context.RenderingParameters = GetRenderingParameters<TParams>();
+		    Context.AgentParameters = agentParameters;
 			var agent = AgentFactory.CreateAgent<TAgent, TViewModel>(Context);
 			agent.PopulateModel();
 			return View(agent.ViewPath, agent.ViewModel);


添加更多关键字

添加更多关键字

--- Il2CppDumper/Outputs/ScriptGenerator.cs
+++ Il2CppDumper/Outputs/ScriptGenerator.cs
@@ -24,7 +24,8 @@
         private List<ulong> genericClassList = new List<ulong>();
         private StringBuilder arrayClassPreHeader = new StringBuilder();
         private StringBuilder arrayClassHeader = new StringBuilder();
-        private static HashSet<string> keyword = new HashSet<string>(StringComparer.Ordinal) { "klass", "monitor", "register", "_cs", "auto", "friend", "template", "near", "far" };
+        private static HashSet<string> keyword = new HashSet<string>(StringComparer.Ordinal)
+        { "klass", "monitor", "register", "_cs", "auto", "friend", "template", "near", "far", "flat", "default" };

         public ScriptGenerator(Il2CppExecutor il2CppExecutor)
         {


Missed a using statement on Pathing.cs.

Missed a using statement on Pathing.cs.

--- ImageTracerNet/Vectorization/Pathing.cs
+++ ImageTracerNet/Vectorization/Pathing.cs
@@ -3,6 +3,8 @@
 using System.Linq;
 using ImageTracerNet.Vectorization.Points;
 using NodeDirList = System.Collections.Generic.List<System.Tuple<int, int>>;
+
+using ImageTracerNet.Extensions;

 namespace ImageTracerNet.Vectorization
 {


Updating assembly information to 0.3.0.

Updating assembly information to 0.3.0.

--- ImgShareData/Properties/AssemblyInfo.cs
+++ ImgShareData/Properties/AssemblyInfo.cs
@@ -10,7 +10,7 @@
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("")]
 [assembly: AssemblyProduct("ImgShareData")]
-[assembly: AssemblyCopyright("Copyright ©  2014")]
+[assembly: AssemblyCopyright("Copyright George Matthews © 2015")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]

@@ -24,6 +24,6 @@
 // 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("0.0.2.0")]
-[assembly: AssemblyFileVersion("0.0.2.0")]
+[assembly: AssemblyVersion("0.0.3.0")]
+[assembly: AssemblyFileVersion("0.0.3.0")]
 [assembly: ComVisible(false)]


Bumped the version.

Bumped the version.

--- JexusManager/Properties/AssemblyInfo.cs
+++ JexusManager/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@
 + "190a69a439dbfb969ebad72a6f7e2e047907da4a7b9c08c6e98d5f1be8b8cafaf3eb978914059a"
 + "245d4bc1")]

-[assembly: AssemblyVersion("12.0.43.0")]
-[assembly: AssemblyFileVersion("12.0.43.0")]
+[assembly: AssemblyVersion("12.0.44.0")]
+[assembly: AssemblyFileVersion("12.0.44.0")]


Allow comma on same line as closing brace

--- Jubjubnest.Style.DotNet/LineAnalyzer.cs
+++ Jubjubnest.Style.DotNet/LineAnalyzer.cs
@@ -220,7 +220,7 @@
 		/// <summary>
 		/// Close brace validation regex.
 		/// </summary>
-		private static readonly Regex validCloseBrace = new Regex( @"^\s*\}[\s);]*(?://.*)?$" );
+		private static readonly Regex validCloseBrace = new Regex( @"^\s*\}[\s);,]*(?://.*)?$" );

 		/// <summary>
 		/// Check whether the braces are on their own lines.


Allow user agent to be added to from any constructor passing the userAgent

--- JudoPayDotNet/Http/HttpClientWrapper.cs
+++ JudoPayDotNet/Http/HttpClientWrapper.cs
@@ -8,8 +8,6 @@
     using System.Collections.Generic;
     using System.Net.Http.Headers;
     using System.Reflection;
-
-    using JudoPayDotNet.Clients;

     /// <summary>
     /// This client is a simple wrapper of IHttpClient
@@ -23,7 +21,7 @@

         public HttpClientWrapper()
         {
-            HttpClient = CreateHttpClient(null);
+            HttpClient = CreateHttpClient((IEnumerable<ProductInfoHeaderValue>)null);
         }

         public HttpClientWrapper(DelegatingHandler handler)
@@ -31,9 +29,7 @@
             HttpClient = CreateHttpClient(null, handler);
         }

-        public HttpClientWrapper(params DelegatingHandler[] handlers) : this(null, handlers)
-        {
-        }
+        public HttpClientWrapper(params DelegatingHandler[] handlers) : this(null, handlers) { }

         /// <summary>
         /// Initializes a new instance of the HttpWrapper class for senidng messages to the api
@@ -43,18 +39,19 @@
         public HttpClientWrapper(IEnumerable<ProductInfoHeaderValue> userAgent, params DelegatingHandler[] handlers)
         {
             HttpClient = CreateHttpClient(userAgent, handlers);
+            SetUserAgent(HttpClient, userAgent);
         }

         private static HttpClient CreateHttpClient(IEnumerable<ProductInfoHeaderValue> userAgent, params DelegatingHandler[] handlers)
         {
             if (!handlers.Any())
             {
-                return new HttpClient();
+                return CreateHttpClient(userAgent);
             }

             if (handlers.Count() == 1)
             {
-                return new HttpClient(handlers.First());
+                return CreateHttpClient(handlers.First(), userAgent);
             }

             DelegatingHandler currentHandler;
@@ -64,29 +61,34 @@
             for (var i = 1; i < handlers.Length; ++i)
             {
                 currentHandler = handlers[i];
-
                 previousHandler.InnerHandler = currentHandler;
-
                 previousHandler = currentHandler;
             }

             // This is the default delegating handler that actually does the http request
             currentHandler.InnerHandler = new HttpClientHandler();
+            return CreateHttpClient(firstHandler, userAgent);
+        }

-            var httpClient = new HttpClient(firstHandler);
+        private static HttpClient CreateHttpClient(DelegatingHandler handler, IEnumerable<ProductInfoHeaderValue> userAgent)
+        {
+            var httpClient = new HttpClient(handler);
+            SetUserAgent(httpClient, userAgent);

+            return httpClient;
+        }
+
+        private static void SetUserAgent(HttpClient httpClient, IEnumerable<ProductInfoHeaderValue> userAgent)
+        {
             httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(SdkUserAgent);

             if (userAgent != null && userAgent.Any())
             {
-
                 foreach (var productInfoHeaderValue in userAgent)
                 {
                     httpClient.DefaultRequestHeaders.UserAgent.Add(productInfoHeaderValue);
                 }
             }
-
-            return httpClient;
         }

         public Task<HttpResponseMessage> SendAsync(HttpRequestMessage request)
@@ -95,4 +97,4 @@
         }
     }
     // ReSharper restore UnusedMember.Global
-}
+}


Fixing the triggered job runs trimming

Fixing the triggered job runs trimming

--- Kudu.Core/Jobs/TriggeredJobRunLogger.cs
+++ Kudu.Core/Jobs/TriggeredJobRunLogger.cs
@@ -35,7 +35,7 @@
         {
             OldRunsCleanup(triggeredJob.Name, fileSystem, environment, traceFactory, settings);

-            string id = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
+            string id = DateTime.UtcNow.ToString("yyyyMMddHHmmssffff");
             var logger = new TriggeredJobRunLogger(triggeredJob.Name, id, environment, fileSystem, traceFactory);
             var triggeredJobStatus = new TriggeredJobStatus()
             {
@@ -48,7 +48,9 @@

         private static void OldRunsCleanup(string jobName, IFileSystem fileSystem, IEnvironment environment, ITraceFactory traceFactory, IDeploymentSettingsManager settings)
         {
-            int maxRuns = settings.GetMaxJobRunsHistoryCount();
+            // if max is 5 and we have 5 we still want to remove one to make room for the next
+            // that's why we decrement max value by 1
+            int maxRuns = settings.GetMaxJobRunsHistoryCount() - 1;

             string historyPath = Path.Combine(environment.JobsDataPath, Constants.TriggeredPath, jobName);
             DirectoryInfoBase historyDirectory = fileSystem.DirectoryInfo.FromDirectoryName(historyPath);


ignore analytics for local requests

ignore analytics for local requests

--- LandmineWeb/Views/Shared/_Layout.cshtml
+++ LandmineWeb/Views/Shared/_Layout.cshtml
@@ -23,8 +23,12 @@

     @Styles.Render("~/Content/css")
     @Html.Partial("_Rollbar")
-    @Html.Partial("_GoogleAnalytics")
-    @Html.Partial("_AppInsights")
+
+    @if (!Request.IsLocal)
+    {
+        @Html.Partial("_GoogleAnalytics")
+        @Html.Partial("_AppInsights")
+    }
 </head>
 <body>
     <div class="navbar navbar-inverse navbar-fixed-top">


Collapsed some assertions into higher level tests in order to make things easier to read and maintain

Credit goes to @tclem for raising this

--- LibGit2Sharp.Tests/RepositoryFixture.cs
+++ LibGit2Sharp.Tests/RepositoryFixture.cs
@@ -61,14 +61,9 @@
         }

         [Test]
-        public void CreateRepoWithEmptyStringThrows()
+        public void CreatingRepoWithBadParamsThrows()
         {
             Assert.Throws<ArgumentException>(() => Repository.Init(string.Empty));
-        }
-
-        [Test]
-        public void CreateRepoWithNullThrows()
-        {
             Assert.Throws<ArgumentNullException>(() => Repository.Init(null));
         }

@@ -169,20 +164,12 @@
         }

         [Test]
-        public void LookupWithEmptyStringThrows()
+        public void LookingUpWithBadParamsThrows()
         {
             using (var repo = new Repository(Constants.TestRepoPath))
             {
                 Assert.Throws<ArgumentException>(() => repo.Lookup(string.Empty));
                 Assert.Throws<ArgumentException>(() => repo.Lookup<GitObject>(string.Empty));
-            }
-        }
-
-        [Test]
-        public void LookupWithNullThrows()
-        {
-            using (var repo = new Repository(Constants.TestRepoPath))
-            {
                 Assert.Throws<ArgumentNullException>(() => repo.Lookup((string)null));
                 Assert.Throws<ArgumentNullException>(() => repo.Lookup((ObjectId)null));
                 Assert.Throws<ArgumentNullException>(() => repo.Lookup<Commit>((string)null));
@@ -220,14 +207,9 @@
         }

         [Test]
-        public void OpeningRepositoryWithEmptyPathThrows()
+        public void OpeningRepositoryWithBadParamsThrows()
         {
             Assert.Throws<ArgumentException>(() => new Repository(string.Empty));
-        }
-
-        [Test]
-        public void OpeningRepositoryWithNullPathThrows()
-        {
             Assert.Throws<ArgumentNullException>(() => new Repository(null));
         }

@@ -244,19 +226,11 @@
         }

         [Test]
-        public void CallingExistsWithEmptyThrows()
+        public void CheckingForObjectExistenceWithBadParamsThrows()
         {
             using (var repo = new Repository(Constants.TestRepoPath))
             {
                 Assert.Throws<ArgumentException>(() => repo.HasObject(string.Empty));
-            }
-        }
-
-        [Test]
-        public void CallingExistsWithNullThrows()
-        {
-            using (var repo = new Repository(Constants.TestRepoPath))
-            {
                 Assert.Throws<ArgumentNullException>(() => repo.HasObject(null));
             }
         }


Simplify naming

Simplify naming

--- Library/Widgets/ListView/RowListView.cs
+++ Library/Widgets/ListView/RowListView.cs
@@ -93,15 +93,15 @@
 			this.Margin = new BorderDouble(6, 0, 6, 6);
 			this.theme = theme;

-			var topToBottomLayout = new FlowLayoutWidget(FlowDirection.TopToBottom) { HAnchor = HAnchor.Stretch };
-
-			var topContentsFlowLayout = new FlowLayoutWidget(FlowDirection.LeftToRight) { HAnchor = HAnchor.Stretch };
+			var column = new FlowLayoutWidget(FlowDirection.TopToBottom) { HAnchor = HAnchor.Stretch };
+
+			var row = new FlowLayoutWidget(FlowDirection.LeftToRight) { HAnchor = HAnchor.Stretch };

 			var leftColumn = new FlowLayoutWidget(FlowDirection.LeftToRight)
 			{
 				VAnchor = VAnchor.Top | VAnchor.Fit
 			};
-			topContentsFlowLayout.AddChild(leftColumn);
+			row.AddChild(leftColumn);

 			imageWidget = new ImageWidget(thumbWidth, thumbHeight)
 			{
@@ -142,10 +142,10 @@

 			middleColumn.AddChild(partLabel);

-			topContentsFlowLayout.AddChild(middleColumn);
-
-			topToBottomLayout.AddChild(topContentsFlowLayout);
-			this.AddChild(topToBottomLayout);
+			row.AddChild(middleColumn);
+
+			column.AddChild(row);
+			this.AddChild(column);
 		}

 		public override async void OnLoad(EventArgs args)


Unit tests for specialized LowerBound version

--- Main/tests/Algorithms/LowerBoundTest.cs
+++ Main/tests/Algorithms/LowerBoundTest.cs
@@ -21,6 +21,9 @@
 			var list2 = list.Cast<IComparable<double>>().ToList();
 			Assert.That(() => list2.LowerBound(10.0, from, list.Count)
 				, Throws.InstanceOf(typeof(ArgumentOutOfRangeException)));
+			// specific version
+			Assert.That(() => list.LowerBound(10.0, from, list.Count)
+				, Throws.InstanceOf(typeof(ArgumentOutOfRangeException)));
 		}

 		[Test]
@@ -34,6 +37,8 @@
 			// IComparable version
 			var list2 = list.Cast<IComparable<double>>().ToList();
 			Assert.That(() => list2.LowerBound(10.0, 0, to), Throws.InstanceOf(typeof(ArgumentOutOfRangeException)));
+			// specific version
+			Assert.That(() => list.LowerBound(10.0, 0, to), Throws.InstanceOf(typeof(ArgumentOutOfRangeException)));
 		}

@@ -48,6 +53,8 @@
 			// IComparable version
 			var list2 = list.Cast<IComparable<double>>().ToList();
 			Assert.That(() => list2.LowerBound(10.0, 0, to), Throws.InstanceOf(typeof(ArgumentOutOfRangeException)));
+			// specific version
+			Assert.That(() => list.LowerBound(10.0, 0, to), Throws.InstanceOf(typeof(ArgumentOutOfRangeException)));
 		}

 		[Test]
@@ -62,6 +69,8 @@
 			// IComparable version
 			var list2 = list.Cast<IComparable<double>>().ToList();
 			Assert.That(() => list2.LowerBound(10.0, from, to), Throws.ArgumentException);
+			// specific version
+			Assert.That(() => list.LowerBound(10.0, from, to), Throws.ArgumentException);
 		}

 		[Test]
@@ -80,6 +89,8 @@
 			// IComparable version
 			var list2 = list.Cast<IComparable<double>>().ToList();
 			Assert.That(list2.LowerBound(value, from, to), Is.EqualTo(expected));
+			// specific version
+			Assert.That(list.LowerBound(value, from, to), Is.EqualTo(expected));
 		}

 		[Test]
@@ -108,6 +119,8 @@
 			// IComparable version
 			var list2 = list.Cast<IComparable<double>>().ToList();
 			Assert.That(list2.LowerBound(value, from), Is.EqualTo(expected));
+			// specific version
+			Assert.That(list.LowerBound(value, from), Is.EqualTo(expected));
 		}

 		[Test]
@@ -129,6 +142,8 @@
 			// IComparable version
 			var list2 = list.Cast<IComparable<double>>().ToList();
 			Assert.That(list2.LowerBound(value), Is.EqualTo(expected));
+			// specific version
+			Assert.That(list.LowerBound(value), Is.EqualTo(expected));
 		}
 	}
 }


Updated load tests

Updated load tests

--- LoadTest/Program.cs
+++ LoadTest/Program.cs
@@ -1,29 +1,14 @@
-//#1
-// Write: 7865ms 9.7MB/s
-// Read: 17392ms 4.39MB / s
-// ASync Read: 2935ms 25.99MB / s
-// #2
-// Write: 14,115ms 5.41MB/s
-// Read: 6,226ms 12.25MB/s
-
-// #3
-// Compress: 11801ms 6.47MB / s
-// Decompress: 6967ms 10.95MB / s
-
-// #4
-// Compress: 10291ms 7.41MB/s
-// Decompress: 5819ms 13.11MB / s
-
+
 // #5
-// FIBONACCI
+// FIBONACCI (Gen2)
 // Compress: 5986ms 12.75MB / s Total 38MB
 // Decompress: 3455ms 22.08MB / s
-// VLQ
+
+// VLQ (Gen2)
 // Compress: 386ms 197.65MB / s Total 36MB
 // Decompress: 874ms 87.29MB / s

 using System.Diagnostics;
-using InvertedTomato.Compression.Integers.Gen2;

 var min = 100000;
 var count = 10000000;
@@ -35,68 +20,75 @@
     input.Add((UInt64) v);
 }

-//////////////////////////////////////////
-Console.WriteLine("FIBONACCI");
-Codec wave2Codec = new FibonacciCodec();
-var compressed = new MemoryStream(count * 5);
-
-// Compress
-var stopWatch = Stopwatch.StartNew();
-wave2Codec.EncodeMany(compressed, input.ToArray());
-stopWatch.Stop();
-Console.WriteLine("Compress: " + stopWatch.ElapsedMilliseconds + "ms " + Math.Round((Double) count * 1000 * 8 / 1024 / 1024 / stopWatch.ElapsedMilliseconds, 2) + "MB/s Total " + compressed.Length / 1024 / 1024 + "MB");
-
-// Rewind
-compressed.Position = 0;
-
-// Decompress
-stopWatch = Stopwatch.StartNew();
-var output = new UInt64[count];
-wave2Codec.DecodeMany(compressed, output);
-stopWatch.Stop();
-Console.WriteLine("Decompress: " + stopWatch.ElapsedMilliseconds + "ms " + Math.Round((Double) count * 1000 * 8 / 1024 / 1024 / stopWatch.ElapsedMilliseconds, 2) + "MB/s");
-
-// Validate
-var pos = 0;
-for (var v = min; v < min + count; v++)
+void Gen2Test(InvertedTomato.Compression.Integers.Gen2.Codec codec)
 {
-    if ((Int32) output[pos++] != v)
+    // Compress
+    using var stream = new MemoryStream(count * 5);
+    var compressStopwatch = Stopwatch.StartNew();
+    codec.EncodeMany(stream, input.ToArray());
+    compressStopwatch.Stop();
+
+    // Decompress
+    stream.Position = 0;
+    var decompressStopwatch = Stopwatch.StartNew();
+    var output = new UInt64[count];
+    codec.DecodeMany(stream, output);
+    decompressStopwatch.Stop();
+
+    // Validate
+    var pos = 0;
+    for (var v = min; v < min + count; v++)
     {
-        throw new Exception("Incorrect result. Expected " + v + " got " + output[v] + ".");
+        if ((Int32) output[pos++] != v) throw new("Incorrect result. Expected " + v + " got " + output[v] + ".");
     }
+
+    Console.WriteLine("{0,-75} {1,15:N0}ms {2,15:N0}ms {3,15:N}MB",codec.GetType().FullName, compressStopwatch.ElapsedMilliseconds, decompressStopwatch.ElapsedMilliseconds, stream.Length/1024/1024);
 }

-//////////////////////////////////////////
+void Gen3Test(InvertedTomato.Compression.Integers.ICodec codec)
+{
+    // Compress
+    using var stream = new MemoryStream(count * 5);
+    var compressStopwatch = Stopwatch.StartNew();
+    using (var writer = new InvertedTomato.Compression.Integers.StreamBitWriter(stream))
+    {
+        input.ForEach(a=>codec.EncodeUInt64(a,writer));
+    }
+    compressStopwatch.Stop();
+
+    // Decompress
+    stream.Position = 0;
+    var decompressStopwatch = Stopwatch.StartNew();
+    using (var reader = new InvertedTomato.Compression.Integers.StreamBitReader(stream))
+    {
+        input.ForEach(a =>
+        {
+            if (a != codec.DecodeUInt64(reader)) throw new("Incorrect result.");
+        });
+    }
+    decompressStopwatch.Stop();
+
+    Console.WriteLine("{0,-75} {1,15:N0}ms {2,15:N0}ms {3,15:N}MB",codec.GetType().FullName, compressStopwatch.ElapsedMilliseconds, decompressStopwatch.ElapsedMilliseconds, stream.Length/1024/1024);
+}
+
+
+Console.WriteLine("CODEC                      ENCODE TIME         DECODE TIME        RESULT SIZE");
+Console.WriteLine("ThompsonAlpha");
+Gen2Test(new InvertedTomato.Compression.Integers.Gen2.ThompsonAlphaCodec());
+Gen3Test(new InvertedTomato.Compression.Integers.ThompsonAlphaCodec());
+
+Console.WriteLine("Fibonacci");
+Gen2Test(new InvertedTomato.Compression.Integers.Gen2.FibonacciCodec());
+Gen3Test(new InvertedTomato.Compression.Integers.FibonacciCodec());
+
 Console.WriteLine("VLQ");
-wave2Codec = new VlqCodec();
-compressed = new MemoryStream(count * 5);
+Gen2Test(new InvertedTomato.Compression.Integers.Gen2.VlqCodec());
+Gen3Test(new InvertedTomato.Compression.Integers.VlqCodec());

-// Compress
-stopWatch = Stopwatch.StartNew();
-wave2Codec.EncodeMany(compressed, input.ToArray());
-stopWatch.Stop();
-Console.WriteLine("Compress: " + stopWatch.ElapsedMilliseconds + "ms " + Math.Round((Double) count * 1000 * 8 / 1024 / 1024 / stopWatch.ElapsedMilliseconds, 2) + "MB/s Total " + compressed.Length / 1024 / 1024 + "MB");
-
-// Rewind
-compressed.Position = 0;
-
-// Decompress
-stopWatch = Stopwatch.StartNew();
-output = new UInt64[count];
-wave2Codec.DecodeMany(compressed, output);
-stopWatch.Stop();
-Console.WriteLine("Decompress: " + stopWatch.ElapsedMilliseconds + "ms " + Math.Round((Double) count * 1000 * 8 / 1024 / 1024 / stopWatch.ElapsedMilliseconds, 2) + "MB/s");
-
-// Validate
-pos = 0;
-for (var v = min; v < min + count; v++)
-{
-    if ((Int32) output[pos++] != v)
-    {
-        throw new ("Incorrect result. Expected " + v + " got " + output[v] + ".");
-    }
-}
+Console.WriteLine("Raw");
+Gen2Test(new InvertedTomato.Compression.Integers.Gen2.RawCodec());
+Gen3Test(new InvertedTomato.Compression.Integers.RawCodec());

 Console.WriteLine("\nDone.");
 Console.ReadKey(true);


- changed order of initialization to have GearItem last (references other components)
- removed call to Awake() (automatically called by Unity)
- fixed issue with start condition

--- ModComponentMapper/ModComponentPatch.cs
+++ ModComponentMapper/ModComponentPatch.cs
@@ -12,12 +12,11 @@
     {
         public static void Postfix(ModComponent __instance)
         {
-            ConfiguredGearItem(__instance);
             ConfigureInspect(__instance);
             ConfigureFood(__instance);
             ConfigureTool(__instance);

-            __instance.GetComponent<GearItem>().Awake();
+            ConfigureGearItem(__instance);

             PostProcess(__instance);
         }
@@ -30,7 +29,7 @@
             gearItem.m_SkinnedMeshRenderers = ModUtils.NotNull(gearItem.m_SkinnedMeshRenderers);
         }

-        private static void ConfiguredGearItem(ModComponent modComponent)
+        private static void ConfigureGearItem(ModComponent modComponent)
         {
             GameObject gameObject = modComponent.gameObject;

@@ -39,7 +38,7 @@
             gearItem.m_WeightKG = modComponent.WeightKG;
             gearItem.m_MaxHP = modComponent.MaxHP;
             gearItem.m_DailyHPDecay = modComponent.DaysToDecay > 0 ? modComponent.MaxHP / modComponent.DaysToDecay : 0;
-            gearItem.m_StartCondition = GearStartCondition.Random;
+            gearItem.OverrideGearCondition(GearStartCondition.Random);

             gearItem.m_LocalizedDisplayName = new LocalizedString();
             gearItem.m_LocalizedDisplayName.m_LocalizationID = modComponent.DisplayNameLocalizationId;


Hash Azure Serive Bus messageId and Validate (#110)

--- NBXplorer/MessageBrokers/AzureBroker.cs
+++ NBXplorer/MessageBrokers/AzureBroker.cs
@@ -7,11 +7,14 @@
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using System.Security.Cryptography;

 namespace NBXplorer.MessageBrokers
 {
 	public class AzureBroker : IBrokerClient
 	{
+		const int MaxMessageIdLength = 128;
+
 		public AzureBroker(ISenderClient client, JsonSerializerSettings serializerSettings)
 		{
 			Client = client;
@@ -33,7 +36,9 @@
 			string jsonMsg = transactionEvent.ToJson(SerializerSettings);
 			var bytes = UTF8.GetBytes(jsonMsg);
 			var message = new Message(bytes);
-			message.MessageId = $"{transactionEvent.DerivationStrategy.GetHash()}-{transactionEvent.TransactionData.Transaction.GetHash()}-{(transactionEvent.TransactionData.BlockId?.ToString() ?? string.Empty)}).ToString()";
+			string msgIdHash = HashMessageId($"{transactionEvent.DerivationStrategy.GetHash()}-{transactionEvent.TransactionData.Transaction.GetHash()}-{(transactionEvent.TransactionData.BlockId?.ToString() ?? string.Empty)}");
+			ValidateMessageId(msgIdHash);
+			message.MessageId = msgIdHash;
 			message.ContentType = transactionEvent.GetType().ToString();
 			await Client.SendAsync(message);
 		}
@@ -53,5 +58,23 @@
 			if(!Client.IsClosedOrClosing)
 				await Client.CloseAsync();
 		}
+
+		private string HashMessageId(string messageId)
+		{
+			HashAlgorithm algorithm = SHA256.Create();
+			return Encoding.UTF8.GetString( algorithm.ComputeHash(Encoding.UTF8.GetBytes(messageId)));
+		}
+
+		private void ValidateMessageId(string messageId)
+		{
+			if (string.IsNullOrEmpty(messageId) )
+			{
+				throw new ArgumentException("MessageIdIsNullOrEmpty");
+			}
+			else if (messageId.Length > MaxMessageIdLength)
+			{
+				throw new ArgumentException($"MessageIdIsOverMaxLength ({MaxMessageIdLength}) :  {messageId} ");
+			}
+		}
 	}
 }


Fix the assertions.

Fix the assertions.

--- NDeproxy.Tests/makeRequestParamsTest.cs
+++ NDeproxy.Tests/makeRequestParamsTest.cs
@@ -42,8 +42,11 @@
             var mc = this.deproxy.makeRequest(url: string.Format("{0}{1}{2}", urlbase, pathPart, queryPart));

             then:
+            Assert.IsNotNull(mc);
+            Assert.IsNotNull(mc.sentRequest);
             Assert.AreEqual(expectedResult, mc.sentRequest.path);
-            Assert.AreEqual(1, mc.handlers.Count);
+            Assert.IsNotNull(mc.handlings);
+            Assert.AreEqual(1, mc.handlings.Count);
             Assert.AreEqual(expectedResult, mc.handlings[0].request.path);

         }


Adding Bob and Alice nodes to tests

Adding Bob and Alice nodes to tests

--- NTumbleBit.Tests/TumblerServerTester.cs
+++ NTumbleBit.Tests/TumblerServerTester.cs
@@ -44,10 +44,12 @@
 			}

 			_NodeBuilder = NodeBuilder.Create(directory);
-			_CoreNode = _NodeBuilder.CreateNode(true);
+			_TumblerNode = _NodeBuilder.CreateNode(false);
+			_AliceNode = _NodeBuilder.CreateNode(false);
+			_BobNode = _NodeBuilder.CreateNode(false);
 			Directory.CreateDirectory(directory);

-			var rpc = _CoreNode.CreateRPCClient();
+			var rpc = _TumblerNode.CreateRPCClient();
 			var confBuilder = new ConfigurationBuilder();
 			confBuilder.AddInMemoryCollection(new[] {
 				new KeyValuePair<string,string>( "NTumbleBit:Network", "regtest" ),
@@ -55,7 +57,6 @@
 				new KeyValuePair<string,string>( "NTumbleBit:RPC:Username", rpc.Credentials.UserName),
 				new KeyValuePair<string,string>( "NTumbleBit:RPC:Password", rpc.Credentials.Password)
 			});
-
 			_Host = new WebHostBuilder()
 				.UseKestrel()
 				.UseConfiguration(confBuilder.Build())
@@ -66,6 +67,7 @@
 				.Build();

 			new Thread(() => _Host.Run(_StopHost.Token)).Start();
+			_NodeBuilder.StartAll();
 		}

 		private static bool TryDelete(string directory, bool throws)
@@ -87,12 +89,12 @@
 			return false;
 		}

-		private readonly CoreNode _CoreNode;
-		public CoreNode CoreNode
+		private readonly CoreNode _TumblerNode;
+		public CoreNode TumblerNode
 		{
 			get
 			{
-				return _CoreNode;
+				return _TumblerNode;
 			}
 		}

@@ -140,6 +142,25 @@
 		}

 		private readonly string _Directory;
+		private readonly CoreNode _AliceNode;
+		public CoreNode AliceNode
+		{
+			get
+			{
+				return _AliceNode;
+			}
+		}
+
+
+		private readonly CoreNode _BobNode;
+		public CoreNode BobNode
+		{
+			get
+			{
+				return _BobNode;
+			}
+		}
+
 		public string BaseDirectory
 		{
 			get


Added sanity tests for npm 1.4.4 search output for parsing package catalog. I haven't added a full set of tests because they take a while to run, and these sanity tests *should* be sufficient to detect if a problem occurs, even though they may not tell us exactly what the problem is - often problems show up as missing or additional packages. Also I don't think the output format has changed between npm 1.4.3 and npm 1.4.4 so it seemed a bit unnecessary to add loads of tests. Relates to work item 704.

--- Nodejs/Tests/NpmTests/NpmSearchTests.cs
+++ Nodejs/Tests/NpmTests/NpmSearchTests.cs
@@ -31,6 +31,7 @@

         private const string Filename_Original = "npmsearchfullcatalog.txt";
         private const string Filename_Npm143 = "npmsearchfullcat_npm143.txt";
+        private const string Filename_Npm144 = "npmsearchfullcat_npm144.txt";

         [ClassInitialize]
         public static void Init(TestContext context) {
@@ -320,36 +321,72 @@
             }
         }

-        [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckNonZeroPackageVersionsExist() {
-            IDictionary<string, IPackage> byName;
-            var target = GetTestPackageList(Filename_Npm143, out byName);
+        private void CheckNonZeroPackageVersionsExist(string testDataFilename) {
+            IDictionary<string, IPackage> byName;
+            var target = GetTestPackageList(testDataFilename, out byName);
             CheckSensibleNumberOfNonZeroVersions(target);
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckCorrectPackageCount() {
-            IDictionary<string, IPackage> byName;
-            var target = GetTestPackageList(Filename_Npm143, out byName);
-            Assert.AreEqual(62068 /*was 62084*/, target.Count, "Unexpected package count in catalogue list.");
-        }
-
-        [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckNoDuplicatePackages() {
-            IDictionary<string, IPackage> byName;
-            var target = GetTestPackageList(Filename_Npm143, out byName);
+        public void Npm143_CheckNonZeroPackageVersionsExist() {
+            CheckNonZeroPackageVersionsExist(Filename_Npm143);
+        }
+
+        [TestMethod, Priority(0)]
+        public void Npm144_CheckNonZeroPackageVersionsExist() {
+            CheckNonZeroPackageVersionsExist(Filename_Npm144);
+        }
+
+        private void CheckCorrectPackageCount(string testDataFilename, int expectedCount) {
+            IDictionary<string, IPackage> byName;
+            var target = GetTestPackageList(testDataFilename, out byName);
+            Assert.AreEqual(expectedCount, target.Count, "Unexpected package count in catalogue list.");
+        }
+
+        [TestMethod, Priority(0)]
+        public void Npm143_CheckCorrectPackageCount() {
+            CheckCorrectPackageCount(Filename_Npm143, 62068);
+        }
+
+        [TestMethod, Priority(0)]
+        public void Npm144_CheckCorrectPackageCount() {
+            CheckCorrectPackageCount(Filename_Npm144, 62208);
+        }
+
+        private void CheckNoDuplicatePackages(string testDataFilename) {
+            IDictionary<string, IPackage> byName;
+            var target = GetTestPackageList(testDataFilename, out byName);
             CheckOnlyOneOfEachPackage(target);
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckListAndDictByNameSameSize() {
-            IDictionary<string, IPackage> byName;
-            var target = GetTestPackageList(Filename_Npm143, out byName);
+        public void Npm143_CheckNoDuplicatePackages() {
+            CheckNoDuplicatePackages(Filename_Npm143);
+        }
+
+        [TestMethod, Priority(0)]
+        public void Npm144_CheckNoDuplicatePackages() {
+            CheckNoDuplicatePackages(Filename_Npm144);
+        }
+
+        private void CheckListAndDictByNameSameSize(string testDataFilename) {
+            IDictionary<string, IPackage> byName;
+            var target = GetTestPackageList(testDataFilename, out byName);
             Assert.AreEqual(target.Count, byName.Count, "Number of packages should be same in list and dictionary.");
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckFirstPackageInCatalog_007() {
+        public void Npm143_CheckListAndDictByNameSameSize() {
+            CheckListAndDictByNameSameSize(Filename_Npm143);
+        }
+
+        [TestMethod, Priority(0)]
+        public void Npm144_CheckListAndDictByNameSameSize() {
+            CheckListAndDictByNameSameSize(Filename_Npm144);
+        }
+
+        [TestMethod, Priority(0)]
+        public void Npm143_CheckFirstPackageInCatalog_007() {
             IDictionary<string, IPackage> byName;
             var target = GetTestPackageList(Filename_Npm143, out byName);
             CheckPackage(
@@ -365,7 +402,7 @@
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckLastPackageInCatalog_zzz() {
+        public void Npm143_CheckLastPackageInCatalog_zzz() {
             IDictionary<string, IPackage> byName;
             var target = GetTestPackageList(Filename_Npm143, out byName);
             CheckPackage(
@@ -381,7 +418,7 @@
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckPackageTruncatedBuildPreReleaseInfo() {
+        public void Npm143_CheckPackageTruncatedBuildPreReleaseInfo() {
             IDictionary<string, IPackage> byName;
             var target = GetTestPackageList(Filename_Npm143, out byName);

@@ -399,7 +436,7 @@
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckPackageMultipleAuthorsTruncated() {
+        public void Npm143_CheckPackageMultipleAuthorsTruncated() {
             IDictionary<string, IPackage> byName;
             var target = GetTestPackageList(Filename_Npm143, out byName);

@@ -417,7 +454,7 @@
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckPackageEqualsInDescription() {
+        public void Npm143_CheckPackageEqualsInDescription() {
             IDictionary<string, IPackage> byName;
             var target = GetTestPackageList(Filename_Npm143, out byName);
             CheckPackage(
@@ -433,7 +470,7 @@
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckPackageAuthorAsEmailAddress() {
+        public void Npm143_CheckPackageAuthorAsEmailAddress() {
             IDictionary<string, IPackage> byName;
             var target = GetTestPackageList(Filename_Npm143, out byName);
             CheckPackage(
@@ -449,7 +486,7 @@
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckPackageNoDescriptionAuthorVersion() {
+        public void Npm143_CheckPackageNoDescriptionAuthorVersion() {
             IDictionary<string, IPackage> byName;
             var target = GetTestPackageList(Filename_Npm143, out byName);

@@ -497,7 +534,7 @@
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckPackageNoVersion() {
+        public void Npm143_CheckPackageNoVersion() {
             IDictionary<string, IPackage> byName;
             var target = GetTestPackageList(Filename_Npm143, out byName);

@@ -525,7 +562,7 @@
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckPackageNoDescription() {
+        public void Npm143_CheckPackageNoDescription() {
             IDictionary<string, IPackage> byName;
             var target = GetTestPackageList(Filename_Npm143, out byName);

@@ -583,7 +620,7 @@
         }

         [TestMethod, Priority(0)]
-        public void Npm143AndLater_CheckPackageWithLongName() {
+        public void Npm143_CheckPackageWithLongName() {
             IDictionary<string, IPackage> byName;
             var target = GetTestPackageList(Filename_Npm143, out byName);


Add outputdir cleaning

Add outputdir cleaning

--- NugetPackagerAssistant/NugetPackager.cs
+++ NugetPackagerAssistant/NugetPackager.cs
@@ -41,6 +41,7 @@
                 GenerateNuspecAndPackDlls();

             PublishNupkgToSharedFolder();
+            CleanOutputDir();
         }

         private void CleanNuspecs()
@@ -71,7 +72,13 @@
         {
             var targetLocation = string.Concat(_publishDirectory, Path.DirectorySeparatorChar, Path.GetFileName(fileName));
             File.Copy(fileName, targetLocation, true);
-            Console.WriteLine("{0} has been published", Path.GetFileName(fileName));
+            Console.WriteLine("    {0} has been published", Path.GetFileName(fileName));
+        }
+
+        private void DeleteFile(string fileName)
+        {
+            File.Delete(fileName);
+            Console.WriteLine("    {0} has been deleted", Path.GetFileName(fileName));
         }

         private void DisplayMenu()
@@ -101,7 +108,7 @@
                 process.WaitForExit(10000);

                 _nuspecs.Add(string.Concat(_tmpDirectoryPath, Path.DirectorySeparatorChar, Path.GetFileNameWithoutExtension(dll), ".nuspec"));
-                Console.WriteLine("{0}.nuspec created", Path.GetFileNameWithoutExtension(dll));
+                Console.WriteLine("    {0}.nuspec created", Path.GetFileNameWithoutExtension(dll));
             }
         }

@@ -188,7 +195,7 @@
                 process.Start();
                 process.WaitForExit(10000);

-                Console.WriteLine("{0}.nupkg created", Path.GetFileNameWithoutExtension(nuspec));
+                Console.WriteLine("    {0}.nupkg created", Path.GetFileNameWithoutExtension(nuspec));
             }
         }

@@ -202,5 +209,18 @@
                 Console.WriteLine("The publication of your .nupkg has complete");
             }
         }
+
+        private void CleanOutputDir()
+        {
+            Console.WriteLine("Would you like us to clean your output folder ?");
+
+            if (ConsoleHelper.PromptChoices(ConsoleKey.Y, ConsoleKey.N) == ConsoleKey.Y)
+            {
+                Directory.GetFiles(_outputDirectory, "*.nupkg").ToList().ForEach(DeleteFile);
+                Console.WriteLine("Your output folder ({0}) is now empty.",_outputDirectory);
+            }
+        }
     }
 }
+
+