"ext-json" in composer.json resolved

"ext-json" in composer.json resolved

--- src/Peachpie.NET.Sdk/ComposerTask.cs
+++ src/Peachpie.NET.Sdk/ComposerTask.cs
@@ -266,6 +266,8 @@
         static string PeachpieSdkVersion => _lazyPeachpieSdkVersion ??= ResolvePeachpieSdkVersion();
         static string _lazyPeachpieSdkVersion;

+        const string Package_PeachpieLibrary = "Peachpie.Library";
+
         /// <summary>
         /// Map of known dependency id's to a corresponding package reference.
         /// </summary>
@@ -273,9 +275,10 @@
         {
             {"ext-curl", "Peachpie.Library.Network"},
             {"ext-sockets", "Peachpie.Library.Network"},
-            {"ext-gettext", "Peachpie.Library"},
-            {"ext-fileinfo", "Peachpie.Library"},
-            {"ext-mbstring", "Peachpie.Library"},
+            {"ext-gettext", Package_PeachpieLibrary},
+            {"ext-fileinfo", Package_PeachpieLibrary},
+            {"ext-mbstring", Package_PeachpieLibrary},
+            {"ext-json", Package_PeachpieLibrary},
             {"ext-mysql", "Peachpie.Library.MySql"},
             {"ext-mysqli", "Peachpie.Library.MySql"},
             {"ext-mssql", "Peachpie.Library.MsSql"},


setting assemblyfileversion for user-agent log

--- src/Plivo/Client/SystemHttpClient.cs
+++ src/Plivo/Client/SystemHttpClient.cs
@@ -111,40 +111,40 @@
                     )
                 );
             _client.DefaultRequestHeaders.Authorization = authHeader;
-            _client.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyVersion);
+            _client.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyFileVersion);
             var baseServerUri = string.IsNullOrEmpty(baseUri) ? "https://api.plivo.com/" + Version.ApiVersion  : baseUri;
             _client.BaseAddress = new Uri(baseServerUri + "/");

             _voiceBaseUriClient = new System.Net.Http.HttpClient(httpClientHandler);
             _voiceBaseUriClient.Timeout = TimeSpan.FromSeconds(5);
             _voiceBaseUriClient.DefaultRequestHeaders.Authorization = authHeader;
-            _voiceBaseUriClient.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyVersion);
+            _voiceBaseUriClient.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyFileVersion);
             var voiceBaseServerUri = string.IsNullOrEmpty(baseUri) ? "https://api.plivo.com/" + Version.ApiVersion  : baseUri;
             _voiceBaseUriClient.BaseAddress = new Uri(voiceBaseServerUri + "/");

             _voiceFallback1Client = new System.Net.Http.HttpClient(httpClientHandler);
             _voiceFallback1Client.Timeout = TimeSpan.FromSeconds(5);
             _voiceFallback1Client.DefaultRequestHeaders.Authorization = authHeader;
-            _voiceFallback1Client.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyVersion);
+            _voiceFallback1Client.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyFileVersion);
             var voiceFallback1Uri = string.IsNullOrEmpty(baseUri) ? "https://api.plivo.com/" + Version.ApiVersion  : baseUri;
             _voiceFallback1Client.BaseAddress = new Uri(voiceFallback1Uri + "/");

             _voiceFallback2Client = new System.Net.Http.HttpClient(httpClientHandler);
             _voiceFallback2Client.Timeout = TimeSpan.FromSeconds(5);
             _voiceFallback2Client.DefaultRequestHeaders.Authorization = authHeader;
-            _voiceFallback2Client.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyVersion);
+            _voiceFallback2Client.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyFileVersion);
             var voiceFallback2Uri = string.IsNullOrEmpty(baseUri) ? "https://api.plivo.com/" + Version.ApiVersion  : baseUri;
             _voiceFallback2Client.BaseAddress = new Uri(voiceFallback2Uri + "/");

             _callInsightsclient = new System.Net.Http.HttpClient(httpClientHandler);
             _callInsightsclient.DefaultRequestHeaders.Authorization = authHeader;
-            _callInsightsclient.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyVersion);
+            _callInsightsclient.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyFileVersion);
             var callInsightsBaseServerUri = "https://stats.plivo.com/" + "v1";
             _callInsightsclient.BaseAddress = new Uri(callInsightsBaseServerUri + "/");

             _lookupClient = new System.Net.Http.HttpClient(httpClientHandler);
             _lookupClient.DefaultRequestHeaders.Authorization = authHeader;
-            _lookupClient.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyVersion);
+            _lookupClient.DefaultRequestHeaders.Add("User-Agent", "plivo-dotnet/" + ThisAssembly.AssemblyFileVersion);
             _lookupClient.BaseAddress = new Uri("https://lookup.plivo.com/v1/");

             _jsonSettings = new JsonSerializerSettings


Updating feat generator tests

Updating feat generator tests

Still more to do, roughing it out right now

--- Tests/Unit/Generators/Abilities/FeatsGeneratorTests.cs
+++ Tests/Unit/Generators/Abilities/FeatsGeneratorTests.cs
@@ -30,13 +30,9 @@
         private Mock<ICollectionsSelector> mockCollectionsSelector;
         private Mock<IAdjustmentsSelector> mockAdjustmentsSelector;
         private Mock<IFeatsSelector> mockFeatsSelector;
-        private List<RacialFeatSelection> racialFeatSelections;
         private List<AdditionalFeatSelection> additionalFeatSelections;
-        private List<CharacterClassFeatSelection> classFeatSelections;
         private Mock<IDice> mockDice;
         private BaseAttack baseAttack;
-        private List<String> overwrittenStrengthFeats;
-        private List<String> cumulativeStrengthFeats;
         private Mock<INameSelector> mockNameSelector;

         [SetUp]
@@ -52,49 +48,113 @@
             race = new Race();
             stats = new Dictionary<String, Stat>();
             skills = new Dictionary<String, Skill>();
-            racialFeatSelections = new List<RacialFeatSelection>();
             additionalFeatSelections = new List<AdditionalFeatSelection>();
-            classFeatSelections = new List<CharacterClassFeatSelection>();
             baseAttack = new BaseAttack();
             stats[StatConstants.Intelligence] = new Stat();
-            overwrittenStrengthFeats = new List<String>();
-            cumulativeStrengthFeats = new List<String>();
-
-            mockFeatsSelector.Setup(s => s.SelectRacial()).Returns(racialFeatSelections);
+
+            mockFeatsSelector.Setup(s => s.SelectRacial(It.IsAny<String>())).Returns(Enumerable.Empty<RacialFeatSelection>());
             mockFeatsSelector.Setup(s => s.SelectAdditional()).Returns(additionalFeatSelections);
-            mockFeatsSelector.Setup(s => s.SelectClassFeats()).Returns(classFeatSelections);
+            mockFeatsSelector.Setup(s => s.SelectClass(It.IsAny<String>())).Returns(Enumerable.Empty<CharacterClassFeatSelection>());
             mockDice.Setup(d => d.Roll(1).d(It.IsAny<Int32>())).Returns(1);
-            mockCollectionsSelector.Setup(s => s.SelectFrom(TableNameConstants.Set.Collection.FeatGroups, TableNameConstants.Set.Collection.Groups.OverwrittenStrengths))
-                .Returns(overwrittenStrengthFeats);
-            mockCollectionsSelector.Setup(s => s.SelectFrom(TableNameConstants.Set.Collection.FeatGroups, TableNameConstants.Set.Collection.Groups.CumulativeStrengths))
-                .Returns(cumulativeStrengthFeats);
-        }
-
-        [Test]
-        public void GetRacialFeats()
-        {
-            AddRacialFeat("feat 1", 9266);
-            AddRacialFeat("feat 2");
+        }
+
+        [Test]
+        public void GetBaseRacialFeats()
+        {
+            var baseRaceFeats = new[]
+            {
+                new RacialFeatSelection { FeatId = "base race feat 1", Focus = "focus" },
+                new RacialFeatSelection { FeatId = "base race feat 2", Strength = 9266, Frequency = new Frequency { Quantity = 42, TimePeriod = "fortnight" } };
+            };
+
+            race.BaseRace.Id = "baseRaceId";
+            mockFeatsSelector.Setup(s => s.SelectRacial("baseRaceId")).Returns(baseRaceFeats);

             var feats = featsGenerator.GenerateWith(characterClass, race, stats, skills, baseAttack);
             var first = feats.First();
             var last = feats.Last();

-            Assert.That(first.Name.Id, Is.EqualTo("feat 1"));
-            Assert.That(first.Focus, Is.EqualTo("9266"));
-            Assert.That(last.Name.Id, Is.EqualTo("feat 2"));
+            Assert.That(first.Name.Id, Is.EqualTo("base race feat 1"));
+            Assert.That(first.Focus, Is.EqualTo("focus"));
+            Assert.That(first.Strength, Is.EqualTo(0));
+            Assert.That(first.Frequency.Quantity, Is.EqualTo(0));
+            Assert.That(first.Frequency.TimePeriod, Is.Empty);
+
+            Assert.That(last.Name.Id, Is.EqualTo("base race feat 2"));
             Assert.That(last.Focus, Is.Empty);
-        }
-
-        private void AddRacialFeat(String id, Int32 strength = 0)
-        {
-            var feat = new RacialFeatSelection();
-            feat.Name.Id = id;
-            feat.Name.Name = id + " name";
-            feat.FeatStrength = strength;
-            racialFeatSelections.Add(feat);
-
-            mockNameSelector.Setup(s => s.Select(id)).Returns(feat.Name.Name);
+            Assert.That(last.Strength, Is.EqualTo(9266));
+            Assert.That(last.Frequency.Quantity, Is.EqualTo(42));
+            Assert.That(last.Frequency.TimePeriod, Is.EqualTo("fortnight"));
+        }
+
+        [Test]
+        public void GetMetaracialFeats()
+        {
+            var metaraceFeats = new[]
+            {
+                new RacialFeatSelection { FeatId = "metarace feat 1", Focus = "focus" },
+                new RacialFeatSelection { FeatId = "metarace feat 2", Strength = 9266, Frequency = new Frequency { Quantity = 42, TimePeriod = "fortnight" } };
+            };
+
+            race.Metarace.Id = "metaraceId";
+            mockFeatsSelector.Setup(s => s.SelectRacial("metaraceId")).Returns(metaraceFeats);
+
+            var feats = featsGenerator.GenerateWith(characterClass, race, stats, skills, baseAttack);
+            var first = feats.First();
+            var last = feats.Last();
+
+            Assert.That(first.Name.Id, Is.EqualTo("metarace feat 1"));
+            Assert.That(first.Focus, Is.EqualTo("focus"));
+            Assert.That(first.Strength, Is.EqualTo(0));
+            Assert.That(first.Frequency.Quantity, Is.EqualTo(0));
+            Assert.That(first.Frequency.TimePeriod, Is.Empty);
+
+            Assert.That(last.Name.Id, Is.EqualTo("metarace feat 2"));
+            Assert.That(last.Focus, Is.Empty);
+            Assert.That(last.Strength, Is.EqualTo(9266));
+            Assert.That(last.Frequency.Quantity, Is.EqualTo(42));
+            Assert.That(last.Frequency.TimePeriod, Is.EqualTo("fortnight"));
+        }
+
+        [Test]
+        public void GetMetaracialSpeciesFeats()
+        {
+            var speciesFeats = new[]
+            {
+                new RacialFeatSelection { FeatId = "metarace species feat 1", Focus = "focus" },
+                new RacialFeatSelection { FeatId = "metarace species feat 2", Strength = 9266, Frequency = new Frequency { Quantity = 42, TimePeriod = "fortnight" } };
+            };
+
+            race.MetaraceSpecies = "metarace species";
+            mockFeatsSelector.Setup(s => s.SelectRacial("metarace species")).Returns(speciesFeats);
+
+            var feats = featsGenerator.GenerateWith(characterClass, race, stats, skills, baseAttack);
+            var first = feats.First();
+            var last = feats.Last();
+
+            Assert.That(first.Name.Id, Is.EqualTo("metarace species feat 1"));
+            Assert.That(first.Focus, Is.EqualTo("focus"));
+            Assert.That(first.Strength, Is.EqualTo(0));
+            Assert.That(first.Frequency.Quantity, Is.EqualTo(0));
+            Assert.That(first.Frequency.TimePeriod, Is.Empty);
+
+            Assert.That(last.Name.Id, Is.EqualTo("metarace species feat 2"));
+            Assert.That(last.Focus, Is.Empty);
+            Assert.That(last.Strength, Is.EqualTo(9266));
+            Assert.That(last.Frequency.Quantity, Is.EqualTo(42));
+            Assert.That(last.Frequency.TimePeriod, Is.EqualTo("fortnight"));
+        }
+
+        [Test]
+        public void GetAllRacialFeats()
+        {
+            Assert.Fail();
+        }
+
+        [Test]
+        public void IfFeatIdAndStrengthAndFocusAndTimePeriodAreEqual_CombineFrequencyQuantity()
+        {
+            Assert.Fail();
         }

         [Test]


Fixed missing $

Fixed missing $

--- src/SampSharp.GameMode/API/Native.cs
+++ src/SampSharp.GameMode/API/Native.cs
@@ -410,7 +410,7 @@
                     var nativeFunction = Load(attribute.Name, attribute.Lengths, parameterTypes);
                     if (nativeFunction == null)
                     {
-                        FrameworkLog.WriteLine(FrameworkMessageLevel.Warning, "Could not load native '{attribute.Name}'");
+                        FrameworkLog.WriteLine(FrameworkMessageLevel.Warning, $"Could not load native '{attribute.Name}'");
                         continue;
                     }

@@ -552,4 +552,4 @@
             [FieldOffset(0)] public float Float;
         }
     }
-}+}


Fixed a small issue with rating calculation.

--- Engines/H3/StatTracker.cs
+++ Engines/H3/StatTracker.cs
@@ -138,7 +138,7 @@
             // Max Rating is 100
             s_Rating0 = s_Rating0 > 100.0 ? 100.0 : s_Rating0;

-            return (uint) Math.Ceiling((Math.Ceiling(s_Rating0) / 100.0) * 6.0);
+            return (uint) Math.Ceiling((Math.Round(s_Rating0) / 100.0) * 6.0);
         }

         private uint CalculateRating1(Stats p_Stats)
@@ -199,7 +199,7 @@
             // Max Rating is 100
             s_Rating1 = s_Rating1 > 100.0 ? 100.0 : s_Rating1;

-            return (uint) Math.Ceiling((Math.Ceiling(s_Rating1) / 100.0) * 6.0);
+            return (uint) Math.Ceiling((Math.Round(s_Rating1) / 100.0) * 6.0);
         }
     }
 }


--- LmpClient/Systems/VesselLockSys/VesselLockSystem.cs
+++ LmpClient/Systems/VesselLockSys/VesselLockSystem.cs
@@ -75,6 +75,9 @@
                 if (_spectateMessage != null)
                     _spectateMessage.duration = 0f;
                 _spectateMessage = LunaScreenMsg.PostScreenMessage(SpectatingMessage, 1000 * 2, ScreenMessageStyle.UPPER_CENTER);
+                //Do auto sync to subspace of target the player is spectating
+                var targetPlayerSubspace = Warp.WarpSystem.Singleton.GetPlayerSubspace($"{GetVesselOwner}");
+                Warp.WarpSystem.Singleton.SyncToSubspace(targetPlayerSubspace);
             }
             else
             {


Increased perf test allowance due to slower running on Chrom

--- Spa/NakedObjects.Spa.Selenium.Test/tests/PerformanceTests.cs
+++ Spa/NakedObjects.Spa.Selenium.Test/tests/PerformanceTests.cs
@@ -29,7 +29,7 @@
             }
             stopWatch.Stop();
             var time = stopWatch.ElapsedMilliseconds;
-            Assert.IsTrue(time < 130000, string.Format("Elapsed time was {0} milliseconds",time));
+            Assert.IsTrue(time < 140000, string.Format("Elapsed time was {0} milliseconds",time));
         }

     }
@@ -66,7 +66,7 @@
         }
     }

-    //[TestClass]
+    [TestClass]
     public class PerformanceTestsFirefox : PerformanceTests
     {
         [ClassInitialize]


testing function added

testing function added

--- Discorgimon/Program.cs
+++ Discorgimon/Program.cs
@@ -123,11 +123,17 @@
                 case "attack": Attack(); break;
                 case "heal": Heal(); break;
                 case "showall": ShowAll(); break;
-                    //DEBUG
+                //DEBUG
+                case "testing": testing(); break;
                 case "dlevel": DEBUGLevel(); break;
                 case "dcreate": DEBUGCreate(); break;
                 default: Output($"You failed to {input.Command}"); break;
             }
+        }
+
+        void testing()
+        {
+            Output("```testing");
         }

         //Private Methods:


update the ignore words.

update the ignore words.

--- src/Thrinax/Extract/HtmlToArticle.cs
+++ src/Thrinax/Extract/HtmlToArticle.cs
@@ -50,7 +50,7 @@
         /// 正文中很难出现的词语，打分时每次出现会扣除五分；所个词语用 ‘,’ 隔开
         /// </summary>
         private static string ContentIgnoreText = ConfigurationManager.AppSettings["Thrinax.ContentIgnoreText"] ??
-            @"版权均属于,Copyright,网站地图,商务合作,书面授权,不得转载,转载自其它媒体,声明：,仅供投资者参考,不构成投资建议,关于我们,ICP备,公网安备,网上传播视听节目许可证,ICP证";
+                                                                      @"版权均属于,Copyright,网站地图,商务合作,书面授权,不得转载,转载自其它媒体,声明：,仅供投资者参考,不构成投资建议,关于我们,ICP备,公网安备,网上传播视听节目许可证,ICP证,证券时报新闻APP,官方新闻客户端,为投资者提供更多财经资讯,扫描二维码添加,来源：,财经资讯、政策解读,股市情报、投资机会";

         /// <summary>
@@ -310,9 +310,9 @@
                         }

                         //对于正文字数少于15个的，每少一个扣2分
-                        if (innerTextWithoutBlack.Length < 15)
-                        {
-                            baseScore -= (15 - innerTextWithoutBlack.Length) * 2;
+                        if (innerTextWithoutBlack.Length < 25)
+                        {
+                            baseScore -= (25 - innerTextWithoutBlack.Length) * 2;
                         }
                     }
                     else


Add unit test

Add unit test


Fully working version with SSL

Fully working version with SSL

--- Tulpep.InternetSimulator/Tulpep.InternetSimulator/Program.cs
+++ Tulpep.InternetSimulator/Tulpep.InternetSimulator/Program.cs
@@ -17,6 +17,7 @@
     {
         private static Options _options = new Options();
         private const string AUTO_IP_ADDRESS = "DHCP";
+        private const string SSL_FRIENDLY_NAME = "Internet Simulator";
         private static Dictionary<string, string> _nicsOriginalConfiguration = new Dictionary<string, string>();
         private static DnsClient _upStreamDnsClient = null;
         static void Main(string[] args)
@@ -26,18 +27,18 @@
             GetDnsConfiguration();
             if(_nicsOriginalConfiguration.Count == 0)
             {
-                Console.WriteLine("Not Enable Network Adpaters found");
+                Console.WriteLine("Not Enable or valid Network Adpaters found");
                 return;
             }

             string certHash = InstallCertificate(new List<string> { "larnia.co", "popo.com", "www.msftncsi.com" });
             if (String.IsNullOrWhiteSpace(certHash))
             {
-                WriteInConsole("ERROR");
+                Console.WriteLine("Cannot manage SSL Certificates in your System");
                 return;
             }

-            if (DeleteOldBinding() && AddSSLBinding(certHash) && StartWebServer() && StartDnsServer()  && ChangeInterfacesToLocalDns())
+            if (AddSSLBinding(certHash) && StartWebServer() && StartDnsServer()  && ChangeInterfacesToLocalDns())
             {
                 Console.WriteLine("Press any key to stop...");
                 Console.ReadLine();
@@ -45,7 +46,10 @@
             else return;

             ChangeInterfacesToOriginalDnsConfig();
-
+            RemoveSSLBinding();
+            RemoveCertificates();
+
+            Console.ReadLine();
         }

         static void GetDnsConfiguration()
@@ -208,16 +212,17 @@
             //Create certificate in Computer Personal store
             string createCertificateScript = string.Format(@"New-SelfSignedCertificate -DnsName {0} -CertStoreLocation {1} -FriendlyName ""{2}""",
                                         string.Join(",", domains),
-                                        @"Cert:\LocalMachine\My",
-                                        "Internet Simulator");
-
+                                        @"Cert:\LocalMachine\My",
+                                        SSL_FRIENDLY_NAME);

             var createCertificatesPs = PowerShell.Create();
-            if(!createCertificatesPs.HadErrors)
-            {
-
-                string certHash = createCertificatesPs.AddScript(createCertificateScript).Invoke()[0].Properties["Thumbprint"].Value.ToString();
-                string copyCertScript = string.Format(@"
+            var createCertifiacateResult = createCertificatesPs.AddScript(createCertificateScript).Invoke();
+            if (createCertificatesPs.HadErrors) return String.Empty;
+            string certHash = createCertifiacateResult[0].Properties["Thumbprint"].Value.ToString();
+
+            WriteInConsole("SLL Certificate created and saved in your Computer Personal Store. Thumbprint " + certHash);
+
+            string copyCertScript = string.Format(@"
                     $srcStore = New-Object System.Security.Cryptography.X509Certificates.X509Store ""My"", ""LocalMachine""
                     $srcStore.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
                     $cert =  $srcStore.certificates -match ""{0}""
@@ -231,16 +236,39 @@

                     ", certHash);

-                var AddCertificateToRootPs = PowerShell.Create();
-                AddCertificateToRootPs.AddScript(copyCertScript).Invoke();
-                if (!AddCertificateToRootPs.HadErrors) return certHash;
-            }
-
-            return String.Empty;
-        }
-
-
-        static bool DeleteOldBinding()
+            var AddCertificateToRootPs = PowerShell.Create();
+            AddCertificateToRootPs.AddScript(copyCertScript).Invoke();
+            if (AddCertificateToRootPs.HadErrors) return String.Empty;
+
+            WriteInConsole("SLL Certificate added to Trusted Root Certification Authorities");
+            return certHash;
+        }
+
+        static bool RemoveCertificates()
+        {
+            var powerShell = PowerShell.Create();
+
+            string removeCertScript = string.Format(@"
+                    Get-ChildItem Cert:\LocalMachine\My | Where {{ $_.FriendlyName -match ""Internet Simulator""}} | Remove-Item
+                    Get-ChildItem Cert:\LocalMachine\Root | Where {{ $_.FriendlyName -match ""Internet Simulator""}} | Remove-Item
+                    ", SSL_FRIENDLY_NAME);
+
+
+            powerShell.AddScript(removeCertScript).Invoke();
+            if (powerShell.HadErrors)
+            {
+                WriteInConsole("Cannot remove SSL generated certificates from the system");
+                return false;
+            }
+            else
+            {
+                WriteInConsole("SLL generated certificates has been remove from the System");
+                return true;
+            }
+        }
+
+
+        static bool RemoveSSLBinding()
         {
             Process process = new Process();
             process.StartInfo.FileName = "netsh";
@@ -249,12 +277,19 @@
             process.StartInfo.RedirectStandardOutput = true;
             process.Start();
             process.WaitForExit();
-            if (process.ExitCode == 0) return true;
-            else return false;
-        }
+            if (process.ExitCode == 0)
+            {
+                WriteInConsole("SSL binding of port 443 has been removed");
+                return true;
+            }
+            return false;
+        }
+

         static bool AddSSLBinding(string certHash)
         {
+            RemoveSSLBinding();
+
             Process process = new Process();
             process.StartInfo.FileName = "netsh";
             process.StartInfo.Arguments = string.Format("http add sslcert ipport=0.0.0.0:443 certhash={0} appid={{{1}}}", certHash, Guid.NewGuid());
@@ -262,8 +297,13 @@
             process.StartInfo.RedirectStandardOutput = true;
             process.Start();
             process.WaitForExit();
-            if (process.ExitCode == 0) return true;
-            else return false;
+            if (process.ExitCode == 0)
+            {
+                WriteInConsole("Added SSL Bindings with generated certificates to 443 Port");
+                return true;
+            }
+            WriteInConsole("Cannot modify SSL Bindings in your System");
+            return false;
         }

         static bool StartWebServer()


Limiting the template references in MS Word export to only templates that are included in the IG.

--- Trifolia.Generation/IG/ImplementationGuideGenerator.cs
+++ Trifolia.Generation/IG/ImplementationGuideGenerator.cs
@@ -60,9 +60,11 @@
                                select t).Distinct().ToList();
             this.templateRelationships = (from tr in this._tdb.ViewTemplateRelationships
                                           join tid in templateIds on tr.ParentTemplateId equals tid
+                                          where templateIds.Contains(tr.ChildTemplateId)
                                           select tr)
                                           .Union(from tr in this._tdb.ViewTemplateRelationships
                                                  join tid in templateIds on tr.ChildTemplateId equals tid
+                                                 where templateIds.Contains(tr.ParentTemplateId)
                                                  select tr)
                                                  .ToList();
             this.constraintReferences = (from t in this.templates


chataltclickandfix

chataltclickandfix


Adds a lightswitch reference tool (#8180)


Clarify FudgeDie special case's formatting

--- UnityProject/Assets/Scripts/Items/Dice/RollFudgeDie.cs
+++ UnityProject/Assets/Scripts/Items/Dice/RollFudgeDie.cs
@@ -4,21 +4,22 @@
 {
 	public override string Examine(Vector3 worldPos = default)
 	{
-		return $"It is showing side {GetFudgeMessage()}";
+		return $"It is showing {GetFudgeMessage()}";
 	}

 	protected override string GetMessage()
 	{
-		return $"The {dieName} lands a {GetFudgeMessage()}";
+		return $"The {dieName} lands {GetFudgeMessage()}";
 	}

 	private string GetFudgeMessage()
 	{
+		// Result 2 is a strange side, we modify the formatting such that it reads "a... what?".
 		if (result == 2)
 		{
-			return specialFaces[1].ToString();
+			return $"a{specialFaces[1]}";
 		}

-		return $"{specialFaces[result - 1]}.";
+		return $"a {specialFaces[result - 1]}.";
 	}
 }


Panorama "names" now appears to have 8 bytes

--- ValveResourceFormat/Resource/ResourceTypes/Panorama.cs
+++ ValveResourceFormat/Resource/ResourceTypes/Panorama.cs
@@ -10,7 +10,8 @@
         public class NameEntry
         {
             public string Name { get; set; }
-            public uint CRC32 { get; set; } // TODO: unconfirmed
+            public uint Unknown1 { get; set; } // TODO: unconfirmed
+            public uint Unknown2 { get; set; } // TODO: unconfirmed
         }

         public List<NameEntry> Names { get; }
@@ -30,22 +31,22 @@
             CRC32 = reader.ReadUInt32();

             var size = reader.ReadUInt16();
-            int headerSize = 4 + 2;

             for (var i = 0; i < size; i++)
             {
                 var entry = new NameEntry
                 {
                     Name = reader.ReadNullTermString(Encoding.UTF8),
-                    CRC32 = reader.ReadUInt32(),
+                    Unknown1 = reader.ReadUInt32(), // TODO: This might be uint64 and be m_nId, same as RERL
+                    Unknown2 = reader.ReadUInt32(),
                 };

                 Names.Add(entry);
-
-                headerSize += entry.Name.Length + 1 + 4; // string length + null byte + 4 bytes
             }

-            Data = reader.ReadBytes((int)Size - headerSize);
+            var headerSize = reader.BaseStream.Position - Offset;
+
+            Data = reader.ReadBytes((int)Size - (int)headerSize);

             if (Crc32.Compute(Data) != CRC32)
             {


Added a dummy implementation of the Imports property because JetBrains wants it...

--- VisualStudio/ProjectBase/Automation/VSProject/OAVSProject.cs
+++ VisualStudio/ProjectBase/Automation/VSProject/OAVSProject.cs
@@ -10,6 +10,8 @@
  * ***************************************************************************/

 using System;
+using System.Collections;
+using System.Collections.Generic;
 using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Runtime.InteropServices;
@@ -28,12 +30,14 @@
         #region fields
         private ProjectNode project;
         private OAVSProjectEvents events;
+        private OAVSProjectImports imports;
         #endregion

         #region ctors
         internal OAVSProject(ProjectNode project)
         {
             this.project = project;
+            this.imports = new OAVSProjectImports(this.Project);
         }
         #endregion

@@ -98,15 +102,14 @@
         public virtual string GetUniqueFilename(object pDispatch, string bstrRoot, string bstrDesiredExt)
         {
 			Debug.Fail("VSProject.GetUniqueFilename not implemented");
-            throw new NotImplementedException();
+            throw new NotImplementedException();
         }

         public virtual Imports Imports
         {
             get
             {
-				Debug.Fail("VSProject.Imports not implemented");
-                throw new NotImplementedException();
+                return imports;
             }
         }

@@ -183,12 +186,14 @@
     {
         #region fields
         private OAVSProject vsProject;
+        private VSLangProj.ImportsEvents importsEvents;
         #endregion

         #region ctors
         public OAVSProjectEvents(OAVSProject vsProject)
         {
             this.vsProject = vsProject;
+            this.importsEvents = new VSLangProj.ImportsEventsClass();
         }
         #endregion

@@ -207,8 +212,7 @@
         {
             get
             {
-				Debug.Fail("VSProjectEvents.ImportsEvents not implemented");
-                throw new NotImplementedException();
+                return importsEvents;
             }
         }

@@ -223,4 +227,85 @@
         #endregion
     }

+    public class OAVSProjectImports : VSLangProj.Imports
+    {
+        EnvDTE.Project project;
+        List<string> imports;
+
+        internal OAVSProjectImports( EnvDTE.Project prj)
+        {
+            project = prj;
+            imports = new List<string>();
+        }
+
+        public EnvDTE.Project ContainingProject
+        {
+            get
+            {
+                return project;
+            }
+        }
+
+        public int Count
+        {
+            get
+            {
+                return imports.Count;
+            }
+        }
+
+        public DTE DTE
+        {
+            get
+            {
+                return project.DTE;
+            }
+        }
+
+        public object Parent
+        {
+            get
+            {
+                return project;
+            }
+        }
+
+        public void Add(string bstrImport)
+        {
+            imports.Add(bstrImport);
+        }
+
+        public IEnumerator GetEnumerator()
+        {
+            return imports.GetEnumerator();
+        }
+
+        public string Item(int lIndex)
+        {
+            if (lIndex >= 0 && lIndex < imports.Count)
+                return imports[lIndex];
+            return null;
+        }
+
+        public void Remove(object index)
+        {
+            if (index is Int32)
+            {
+                int iIndex = (Int32)index;
+                if (iIndex > 0 && iIndex <= imports.Count)
+                    imports.Remove(imports[iIndex - 1]);
+            }
+            else if (index is String)
+            {
+                string sIndex = index as String;
+                if (imports.Contains(sIndex))
+                {
+                    imports.Remove(sIndex);
+                }
+            }
+        }
+    }
+
+
 }
+


(VsIntegration) Correction on MultiLine formatting to align Attributes

--- VisualStudio/ProjectPackage/Editors/Formatting/Formatting.cs
+++ VisualStudio/ProjectPackage/Editors/Formatting/Formatting.cs
@@ -324,7 +324,10 @@
                                 //
                                 if (lineContinue==1)
                                 {
-                                    indentSize = prevIndentSize + continueOffset;
+                                    if ( start != '[')
+                                    {
+                                        indentSize = prevIndentSize + continueOffset;
+                                    }
                                 }
                                 else if (lineContinue>1)
                                 {
@@ -334,7 +337,8 @@
                                 {
                                     indentSize = getDesiredIndentationInDocument(snapLine, regions, out inComment);
                                 }
-                                if (!inComment && (end == ';'))
+                                // Not in comment, Multiple line but not Attribute
+                                if (!inComment && (end == ';') )
                                 {
                                     if (lineContinue==0)
                                     {


super simplify conversion control.

super simplify conversion control.

--- WalletWasabi.Fluent/Controls/CurrencyEntryBox.axaml.cs
+++ WalletWasabi.Fluent/Controls/CurrencyEntryBox.axaml.cs
@@ -18,9 +18,6 @@
 		public static readonly StyledProperty<decimal> AmountBtcProperty =
 			AvaloniaProperty.Register<CurrencyEntryBox, decimal>(nameof(AmountBtc), defaultBindingMode: BindingMode.TwoWay);

-		public static readonly StyledProperty<decimal> ConversionProperty =
-			AvaloniaProperty.Register<CurrencyEntryBox, decimal>(nameof(Conversion));
-
 		public static readonly StyledProperty<string> ConversionTextProperty =
 			AvaloniaProperty.Register<CurrencyEntryBox, string>(nameof(ConversionText));

@@ -38,8 +35,6 @@

 		private Button? _swapButton;
 		private CompositeDisposable? _disposable;
-		private bool _allowConversions = true;
-		private bool _allowAmountUpdate = true;
 		private readonly CultureInfo _customCultureInfo;
 		private readonly char _decimalSeparator = '.';
 		private readonly char _groupSeparator = ' ';
@@ -59,49 +54,10 @@
 				}
 			};

-			this.GetObservable(TextProperty).Subscribe(_ => DoConversion());
-			this.GetObservable(ConversionRateProperty).Subscribe(_ => DoConversion());
-			this.GetObservable(ConversionCurrencyCodeProperty).Subscribe(_ => DoConversion());
-			this.GetObservable(AmountBtcProperty).Subscribe(x =>
-			{
-				if (_allowAmountUpdate && x > 0)
-				{
-					if (IsConversionReversed)
-					{
-						_allowConversions = false;
-
-						Conversion = x;
-
-						var fiatValue = BitcoinToFiat(x);
-						Text = FormatFiatValue(fiatValue);
-
-						_allowConversions = true;
-					}
-					else
-					{
-						var formatted = FormatBtcValue(x);
-
-						if (BitcoinInput.TryCorrectAmount(formatted, out var better))
-						{
-							formatted = better;
-						}
-
-						Text = formatted;
-					}
-				}
-			});
-
-			this.GetObservable(ConversionProperty).Subscribe(x =>
-			{
-				if (IsConversionReversed)
-				{
-					ConversionText = FullFormatBtc(x);
-				}
-				else
-				{
-					ConversionText = FullFormatFiat(x);
-				}
-			});
+			this.GetObservable(TextProperty).Subscribe(InputText);
+			this.GetObservable(ConversionRateProperty).Subscribe(_ => UpdateDisplay(false));
+			this.GetObservable(ConversionCurrencyCodeProperty).Subscribe(_ => UpdateDisplay(true));
+			this.GetObservable(AmountBtcProperty).Subscribe(_ => UpdateDisplay(true));

 			Watermark = "0 BTC";
 			Text = string.Empty;
@@ -125,113 +81,75 @@
 			return btcValue * ConversionRate;
 		}

-		private void Reverse()
-		{
-			if (ConversionText != string.Empty)
-			{
-				_allowConversions = false;
-
-				if (IsConversionReversed)
-				{
-					if (!string.IsNullOrWhiteSpace(Text))
-					{
-						Text = FormatBtcValue(Conversion);
-					}
-
-					Watermark = "0 BTC";
-				}
-				else
-				{
-					if (!string.IsNullOrWhiteSpace(Text))
-					{
-						Text = FormatFiatValue(Conversion);
-					}
-
-					Watermark = $"0.00 {ConversionCurrencyCode}";
-				}
-
-				IsConversionReversed = !IsConversionReversed;
-
-				_allowConversions = true;
-
-				DoConversion();
-
-				CaretIndex = Text.Length;
-			}
-		}
-
 		protected override void OnGotFocus(GotFocusEventArgs e)
 		{
 			base.OnGotFocus(e);

 			CaretIndex = Text?.Length ?? 0;

-			Dispatcher.UIThread.Post(() => SelectAll());
+			Dispatcher.UIThread.Post(SelectAll);
 		}

 		protected override void OnTextInput(TextInputEventArgs e)
 		{
-			if (_allowConversions)
-			{
-				var inputText = e.Text ?? "";
-				var inputLength = inputText.Length;
-
-				// Check if it has a decimal separator.
-				var trailingDecimal = inputLength > 0 && inputText[^1] == _decimalSeparator;
-				var preComposedText = PreComposeText(e);
-
-				if (!_matchRegexDecimalCharsOnly.IsMatch(preComposedText))
-				{
-					e.Handled = true;
+			var inputText = e.Text ?? "";
+			var inputLength = inputText.Length;
+
+			// Check if it has a decimal separator.
+			var trailingDecimal = inputLength > 0 && inputText[^1] == _decimalSeparator;
+			var preComposedText = PreComposeText(e);
+
+			if (!_matchRegexDecimalCharsOnly.IsMatch(preComposedText))
+			{
+				e.Handled = true;
+				base.OnTextInput(e);
+				return;
+			}
+
+			var match = _matchRegexDecimal.Match(preComposedText);
+
+			// Ignore group chars on count of the whole part of the decimal.
+			var wholeStr = match.Groups["Whole"].ToString();
+			var whole = wholeStr
+				.Replace(_groupSeparator, char.MinValue)
+				.Replace(_decimalSeparator, char.MinValue)
+				.Length;
+
+			var fracStr = match.Groups["Frac"].ToString();
+			var frac = fracStr.Length;
+
+			// Reject and dont process the input if the string doesnt match.
+			if (!match.Success)
+			{
+				e.Handled = true;
+				base.OnTextInput(e);
+				return;
+			}
+
+			// Passthrough the decimal place char or the group separator.
+			switch (inputLength)
+			{
+				case 1 when inputText[0] == _decimalSeparator && !trailingDecimal:
+				case 1 when inputText[0] == _groupSeparator && !fracStr.Contains(_groupSeparator):
 					base.OnTextInput(e);
 					return;
-				}
-
-				var match = _matchRegexDecimal.Match(preComposedText);
-
-				// Ignore group chars on count of the whole part of the decimal.
-				var wholeStr = match.Groups["Whole"].ToString();
-				var whole = wholeStr
-					.Replace(_groupSeparator, char.MinValue)
-					.Replace(_decimalSeparator, char.MinValue)
-					.Length;
-
-				var fracStr = match.Groups["Frac"].ToString();
-				var frac = fracStr.Length;
-
-				// Reject and dont process the input if the string doesnt match.
-				if (!match.Success)
+			}
+
+			if (IsConversionReversed)
+			{
+				// Fiat input restriction is to only allow 2 decimal places.
+				if (frac > 2)
 				{
 					e.Handled = true;
-					base.OnTextInput(e);
-					return;
-				}
-
-				// Passthrough the decimal place char or the group separator.
-				switch (inputLength)
-				{
-					case 1 when inputText[0] == _decimalSeparator && !trailingDecimal:
-					case 1 when inputText[0] == _groupSeparator && !fracStr.Contains(_groupSeparator):
-						base.OnTextInput(e);
-						return;
-				}
-
-				if (IsConversionReversed)
-				{
-					// Fiat input restriction is to only allow 2 decimal places.
-					if (frac > 2)
-					{
-						e.Handled = true;
-					}
-				}
-				else
-				{
-					// Bitcoin input restriction is to only allow 8 decimal places max
-					// and also 8 whole number places.
-					if (whole > 8 && !trailingDecimal || frac > 8)
-					{
-						e.Handled = true;
-					}
+				}
+			}
+			else
+			{
+				// Bitcoin input restriction is to only allow 8 decimal places max
+				// and also 8 whole number places.
+				if (whole > 8 && !trailingDecimal || frac > 8)
+				{
+					e.Handled = true;
 				}
 			}

@@ -269,71 +187,26 @@
 			return "";
 		}

-		private string FormatBtcValue(decimal value)
-		{
-			return string.Format(_customCultureInfo.NumberFormat, "{0:### ### ### ##0.########}", value).Trim();
-		}
-
-		private string FormatFiatValue(decimal value)
-		{
-			return string.Format(_customCultureInfo.NumberFormat, "{0:N2}", value).Trim();
-		}
-
-		private string FullFormatBtc(decimal value)
-		{
-			return $"{FormatBtcValue(value)} BTC";
-		}
-
-		private string FullFormatFiat(decimal value)
-		{
-			return $"≈ {FormatFiatValue(Conversion)}" + (!string.IsNullOrWhiteSpace(ConversionCurrencyCode)
-				? $" {ConversionCurrencyCode}"
+		private static string FormatBtcValue(NumberFormatInfo formatInfo, decimal value)
+		{
+			return string.Format(formatInfo, "{0:### ### ### ##0.########}", value).Trim();
+		}
+
+		private static string FormatFiatValue(NumberFormatInfo formatInfo, decimal value)
+		{
+			return string.Format(formatInfo, "{0:N2}", value).Trim();
+		}
+
+		private static string FullFormatBtc(NumberFormatInfo formatInfo, decimal value)
+		{
+			return $"{FormatBtcValue(formatInfo, value)} BTC";
+		}
+
+		private static string FullFormatFiat(NumberFormatInfo formatInfo, decimal value, string currencyCode)
+		{
+			return $"≈ {FormatFiatValue(formatInfo, value)}" + (!string.IsNullOrWhiteSpace(currencyCode)
+				? $" {currencyCode}"
 				: "");
-		}
-
-		private void DoConversion()
-		{
-			if (_allowConversions)
-			{
-				if (IsConversionReversed)
-				{
-					if (decimal.TryParse(Text, NumberStyles.Number, _customCultureInfo, out var result) && ConversionRate > 0)
-					{
-						CurrencyCode = ConversionCurrencyCode;
-
-						Conversion = FiatToBitcoin(result);
-
-						_allowAmountUpdate = false;
-						AmountBtc = Conversion;
-						_allowAmountUpdate = true;
-					}
-					else
-					{
-						AmountBtc = 0;
-						Conversion = 0;
-						CurrencyCode = ConversionCurrencyCode;
-					}
-				}
-				else
-				{
-					if (decimal.TryParse(Text, NumberStyles.Number, _customCultureInfo, out var result) && ConversionRate > 0)
-					{
-						CurrencyCode = "BTC";
-
-						Conversion = BitcoinToFiat(result);
-
-						_allowAmountUpdate = false;
-						AmountBtc = result;
-						_allowAmountUpdate = true;
-					}
-					else
-					{
-						AmountBtc = 0;
-						Conversion = 0;
-						CurrencyCode = "BTC";
-					}
-				}
-			}
 		}

 		protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
@@ -352,7 +225,84 @@

 		private void SwapButtonOnClick(object? sender, RoutedEventArgs e)
 		{
-			Reverse();
+			IsConversionReversed = !IsConversionReversed;
+			UpdateDisplay(true);
+		}
+
+		private void InputText(string text)
+		{
+			if (string.IsNullOrWhiteSpace(text))
+			{
+				InputBtcValue(0);
+				UpdateDisplay(false);
+			}
+			else
+			{
+				if (IsConversionReversed)
+				{
+					InputFiatString(text);
+				}
+				else
+				{
+					InputBtcString(text);
+				}
+			}
+		}
+
+		private void InputFiatString(string value)
+		{
+			if (decimal.TryParse(value, NumberStyles.Number, _customCultureInfo, out var decimalValue))
+			{
+				InputBtcValue(FiatToBitcoin(decimalValue));
+			}
+
+			UpdateDisplay(false);
+		}
+
+		private void InputBtcString(string value)
+		{
+			if (BitcoinInput.TryCorrectAmount(value, out var better))
+			{
+				value = better;
+			}
+
+			if (decimal.TryParse(value, NumberStyles.Number, _customCultureInfo, out var decimalValue))
+			{
+				InputBtcValue(decimalValue);
+			}
+
+			UpdateDisplay(false);
+		}
+
+		private void InputBtcValue(decimal value)
+		{
+			AmountBtc = value;
+		}
+
+		private void UpdateDisplay(bool updateTextField)
+		{
+			var conversion = BitcoinToFiat(AmountBtc);
+
+			if (IsConversionReversed)
+			{
+				CurrencyCode = ConversionCurrencyCode;
+				ConversionText = FullFormatBtc(_customCultureInfo.NumberFormat, AmountBtc);
+
+				if (updateTextField)
+				{
+					Text = AmountBtc > 0 ? FormatFiatValue(_customCultureInfo.NumberFormat, conversion) : string.Empty;
+				}
+			}
+			else
+			{
+				CurrencyCode = "BTC";
+				ConversionText = FullFormatFiat(_customCultureInfo.NumberFormat, conversion, CurrencyCode);
+
+				if (updateTextField)
+				{
+					Text = AmountBtc > 0 ? FormatBtcValue(_customCultureInfo.NumberFormat, AmountBtc) : string.Empty;
+				}
+			}
 		}

 		public decimal AmountBtc
@@ -361,12 +311,6 @@
 			set => SetValue(AmountBtcProperty, value);
 		}

-		public decimal Conversion
-		{
-			get => GetValue(ConversionProperty);
-			set => SetValue(ConversionProperty, value);
-		}
-
 		public string ConversionText
 		{
 			get => GetValue(ConversionTextProperty);


nullable reference type fixes.

nullable reference type fixes.

--- WalletWasabi.Fluent/ViewModels/RecoverWalletPageViewModel.cs
+++ WalletWasabi.Fluent/ViewModels/RecoverWalletPageViewModel.cs
@@ -14,18 +14,18 @@
     public class RecoveryPageViewModel : NavBarItemViewModel
     {
         private readonly ObservableAsPropertyHelper<Mnemonic?> _currentMnemonic;
-        private IEnumerable<string> _suggestions;
-        private string _selectedTag;
+        private IEnumerable<string>? _suggestions;
+        private string? _selectedTag;

         public ObservableCollection<string> Mnemonics { get; } = new ObservableCollection<string>();

-        public IEnumerable<string> Suggestions
+        public IEnumerable<string>? Suggestions
         {
             get => _suggestions;
             set => this.RaiseAndSetIfChanged(ref _suggestions, value);
         }

-        public string SelectedTag
+        public string? SelectedTag
         {
             get => _selectedTag;
             set => this.RaiseAndSetIfChanged(ref _selectedTag, value);
@@ -34,16 +34,15 @@
         public RecoveryPageViewModel(IScreen screen) : base(screen)
         {
             Suggestions = new Mnemonic(Wordlist.English, WordCount.Twelve).WordList.GetWords();
-
+
             _currentMnemonic = Mnemonics.ToObservableChangeSet().ToCollection()
                 .Select(x => x.Count == 12 ? new Mnemonic(GetTagsAsConcatString()) : default)
                 .ToProperty(this, x => x.CurrentMnemonics);
-
+
             this.WhenAnyValue(x => x.SelectedTag)
                 .Where(x => !string.IsNullOrEmpty(x))
                 .Subscribe(AddMnemonic);
-
-            // TODO: Will try to find ways of doing this better...
+
             this.WhenAnyValue(x => x.CurrentMnemonics)
                 .Subscribe(x => this.RaisePropertyChanged(nameof(Mnemonics)));

@@ -58,10 +57,14 @@
             }
         }

-        private void AddMnemonic(string tagString)
+        private void AddMnemonic(string? tagString)
         {
-            Mnemonics.Add(tagString);
-            SelectedTag = string.Empty;
+	        if (!string.IsNullOrWhiteSpace(tagString))
+	        {
+		        Mnemonics.Add(tagString);
+	        }
+
+	        SelectedTag = string.Empty;
         }

         private string GetTagsAsConcatString()
@@ -69,8 +72,8 @@
             return string.Join(' ', Mnemonics);
         }

-        public Mnemonic? CurrentMnemonics => _currentMnemonic.Value;
-
+        private Mnemonic? CurrentMnemonics => _currentMnemonic.Value;
+
         public override string IconName => "settings_regular";
     }
 }


Added test for filter method in Raster<T>.

--- Drawing/RasterTests.cs
+++ Drawing/RasterTests.cs
@@ -1,5 +1,4 @@
-using System;
-using Free.Core.Drawing;
+using Free.Core.Drawing;
 using NUnit.Framework;

 namespace Free.Core.Tests.Drawing
@@ -247,5 +246,102 @@
 				}
 			}
 		}
+
+		[Test]
+		public static void RasterFilterTests()
+		{
+			int width = 21;
+			int height = 17;
+			int tileWidth = 4;
+			int tileHeight = 3;
+
+			int tileSize = tileWidth * tileHeight;
+			int numberOfTilesX = (width + tileWidth - 1) / tileWidth;
+			int numberOfTilesY = (height + tileHeight - 1) / tileHeight;
+			int numberOfTiles = numberOfTilesX * numberOfTilesY;
+
+			Raster<float> raster = new Raster<float>(width, height, true, tileWidth, tileHeight);
+
+			#region Check raster
+			Assert.AreEqual(width, raster.Width);
+			Assert.AreEqual(height, raster.Height);
+			Assert.AreEqual(1, raster.NumberOfChannels);
+			Assert.AreEqual(PlanarConfiguration.Continuously, raster.PlanarConfiguration);
+
+			Assert.AreEqual(StorageLayout.Tiled, raster.StorageLayout);
+			Assert.AreEqual(tileWidth, raster.TileWidth);
+			Assert.AreEqual(tileHeight, raster.TileHeight);
+			Assert.AreEqual(numberOfTilesX, raster.NumberOfTileX);
+			Assert.AreEqual(numberOfTilesY, raster.NumberOfTileY);
+
+			Assert.NotNull(raster.ChannelTypes);
+			Assert.AreEqual(1, raster.ChannelTypes.Length);
+			Assert.AreEqual(ChannelType.Single, raster.ChannelTypes[0]);
+
+			Assert.NotNull(raster.Data);
+			Assert.AreEqual(numberOfTiles, raster.Data.Length);
+			for (int i = 0; i < raster.Data.Length; i++)
+				Assert.AreEqual(tileSize, raster.Data[i].Length, "raster.Data[{0}]", i);
+			#endregion
+
+			// Add some other values != default.
+			raster[0, 0] = raster[20, 0] = raster[20, 16] = raster[0, 16] = // in corners
+			raster[6, 0] = raster[0, 5] = raster[20, 9] = raster[13, 16] = // on edges
+			raster[16, 5] = raster[6, 8] = raster[10, 13] = 5; // in between
+
+			// Filter the raster.
+			var filtered = raster.Filter(se =>
+			{
+				// If the center if not zero, we count the zeros in the structure element and return it.
+				if (se[se.Length / 2] == 0) return 0;
+
+				int countDefaults = 0;
+				for (int i = 0; i < se.Length; i++)
+				{
+					if (se[i] == 0) countDefaults++;
+				}
+
+				return countDefaults;
+			}, 1.5, float.NaN);
+
+			#region Check filtered
+			Assert.AreEqual(width, filtered.Width);
+			Assert.AreEqual(height, filtered.Height);
+			Assert.AreEqual(1, filtered.NumberOfChannels);
+			Assert.AreEqual(PlanarConfiguration.Continuously, filtered.PlanarConfiguration);
+
+			Assert.AreEqual(StorageLayout.Tiled, filtered.StorageLayout);
+			Assert.AreEqual(tileWidth, filtered.TileWidth);
+			Assert.AreEqual(tileHeight, filtered.TileHeight);
+			Assert.AreEqual(numberOfTilesX, filtered.NumberOfTileX);
+			Assert.AreEqual(numberOfTilesY, filtered.NumberOfTileY);
+
+			Assert.NotNull(filtered.ChannelTypes);
+			Assert.AreEqual(1, filtered.ChannelTypes.Length);
+			Assert.AreEqual(ChannelType.SInt, filtered.ChannelTypes[0]);
+
+			Assert.NotNull(filtered.Data);
+			Assert.AreEqual(numberOfTiles, filtered.Data.Length);
+			for (int i = 0; i < filtered.Data.Length; i++)
+				Assert.AreEqual(tileSize, filtered.Data[i].Length, "raster.Data[{0}]", i);
+			#endregion
+
+			// In the corners, there should be 3 zeros neighboring the cell.
+			Assert.AreEqual(3, filtered[0, 0]);
+			Assert.AreEqual(3, filtered[20, 0]);
+			Assert.AreEqual(3, filtered[20, 16]);
+			Assert.AreEqual(3, filtered[0, 16]);
+
+			// At the edges, there should be 5 zeros neighboring the cell.
+			Assert.AreEqual(5, filtered[6, 0]);
+			Assert.AreEqual(5, filtered[0, 5]);
+			Assert.AreEqual(5, filtered[20, 9]);
+			Assert.AreEqual(5, filtered[13, 16]);
+
+			// At the edges, there should be 8 zeros neighboring the cell.
+			Assert.AreEqual(8, filtered[16, 5]);
+			Assert.AreEqual(8, filtered[6, 8]);
+			Assert.AreEqual(8, filtered[10, 13]);
+		}
 	}
 }


CA-366140: Handle and log exceptions thrown when retrieving data sources.

Signed-off-by: Konstantina Chremmou <a7d1f757a659045fb6db8c1e3849a1c8ad00b97a@citrix.com>

--- XenAdmin/Controls/CustomDataGraph/ArchiveMaintainer.cs
+++ XenAdmin/Controls/CustomDataGraph/ArchiveMaintainer.cs
@@ -191,17 +191,23 @@
                     foreach (DataArchive a in Archives.Values)
                         a.ClearSets();

+                    LoadingInitialData = true;
+                    ArchivesUpdated?.Invoke();
+
                     try
                     {
-                        LoadingInitialData = true;
-                        ArchivesUpdated?.Invoke();
-
                         if (xenObject is Host h)
                             _dataSources = Host.get_data_sources(h.Connection.Session, h.opaque_ref);
                         else if (xenObject is VM vm && vm.power_state == vm_power_state.Running)
                             _dataSources = VM.get_data_sources(vm.Connection.Session, vm.opaque_ref);

                         Get(ArchiveInterval.None, RrdsUri, RRD_Full_InspectCurrentNode, xenObject);
+                    }
+                    catch (Exception e)
+                    {
+                        //Get handles its own exception;
+                        //anything caught here is thrown by the get_data_sources operations
+                        log.Error($"Failed to retrieve data sources for '{xenObject.Name()}'", e);
                     }
                     finally
                     {


Use topmost SystemWindow for popover

Use topmost SystemWindow for popover

- Issue MatterHackers/MCCentral#4775
Popovers appear at incorrect position in presets window

--- MatterControlLib/SlicerConfiguration/SettingsRow.cs
+++ MatterControlLib/SlicerConfiguration/SettingsRow.cs
@@ -147,7 +147,8 @@

 		public override void OnLoad(EventArgs args)
 		{
-			systemWindow = this.Parents<SystemWindow>().FirstOrDefault();
+			// The top level SystemWindow - due to single window implementation details, multiple SystemWindow parents may exist - proceed to the topmost one
+			systemWindow = this.Parents<SystemWindow>().LastOrDefault();
 			base.OnLoad(args);
 		}


fixed test

fixed test

--- Explore/StringRecorder.cs
+++ Explore/StringRecorder.cs
@@ -29,7 +29,7 @@
         {
             recordingBuilder.Append(action.ToString(CultureInfo.InvariantCulture));
             recordingBuilder.Append(' ');
-            recordingBuilder.Append(uniqueKey);
+            recordingBuilder.Append(uniqueKey.Key);
             recordingBuilder.Append(' ');

             recordingBuilder.Append(probability.ToString("0.00000", CultureInfo.InvariantCulture));


Fixed bad implemntation of parameters in EtlCatalogRunner

--- NBi.Core/Etl/IntegrationService/EtlCatalogRunner.cs
+++ NBi.Core/Etl/IntegrationService/EtlCatalogRunner.cs
@@ -3,6 +3,7 @@
 using System.Data.SqlClient;
 using System.Linq;
 using Microsoft.SqlServer.Management.IntegrationServices;
+using System.Collections.Generic;

 namespace NBi.Core.Etl.IntegrationService
 {
@@ -36,6 +37,7 @@
             Catalog catalog;
             PackageInfo package;
             GetPackage(integrationServices, out catalog, out package);
+

             var setValueParameters = new Collection<PackageInfo.ExecutionValueParameterSet>();
             setValueParameters.Add(new PackageInfo.ExecutionValueParameterSet
@@ -44,6 +46,8 @@
                 ParameterName = "SYNCHRONIZED",
                 ParameterValue = 1
             });
+            var parameters = Parameterize(Etl.Parameters);
+            parameters.ToList().ForEach(p => setValueParameters.Add(p));

             long executionIdentifier = package.Execute(Etl.Is32Bits, null, setValueParameters);

@@ -98,6 +102,20 @@
             }
         }

+        protected virtual IEnumerable<PackageInfo.ExecutionValueParameterSet> Parameterize(IEnumerable<EtlParameter> parameters)
+        {
+            foreach (var param in parameters)
+            {
+                var execParam = new PackageInfo.ExecutionValueParameterSet()
+                {
+                    ObjectType = 30,
+                    ParameterName = param.Name,
+                    ParameterValue = param.StringValue
+                };
+                yield return execParam;
+            }
+        }
+
     }
 }


converting to other build result type

converting to other build result type

--- NJasmine/Core/Discovery/NJasmineTestSuiteBuilder.cs
+++ NJasmine/Core/Discovery/NJasmineTestSuiteBuilder.cs
@@ -50,7 +50,7 @@
         {
             if (action == null)
             {
-                var result = new NJasmineDirectBuildResult(new NJasmineUnimplementedTestMethod(position), position);
+                var result = NJasmineBuildResult.ForUnimplementedTest(position);

                 _buildContext.NameGenator.NameTest(description, _parent, result);

@@ -104,9 +104,7 @@
         {
             if (action == null)
             {
-                var unimplementedTest = new NJasmineUnimplementedTestMethod(position);
-
-                var buildResult = new NJasmineDirectBuildResult(unimplementedTest, position);
+                var buildResult = NJasmineBuildResult.ForUnimplementedTest(position);

                 _buildContext.NameGenator.NameTest(description, _parent, buildResult);


C#: Make static member on generic class private

--- csharp/extractor/Semmle.Util/FuzzyDictionary.cs
+++ csharp/extractor/Semmle.Util/FuzzyDictionary.cs
@@ -133,7 +133,7 @@
         /// </summary>
         /// <param name="input">The string to enumerate.</param>
         /// <returns>The sequence of integers.</returns>
-        public static IEnumerable<int> ExtractIntegers(string input)
+        private static IEnumerable<int> ExtractIntegers(string input)
         {
             var inNumber = false;
             var value = 0;


Removed '\'' from the list of valid comment chars.

--- SharpConfig/Configuration.cs
+++ SharpConfig/Configuration.cs
@@ -39,7 +39,7 @@
         {
             mNumberFormat = CultureInfo.InvariantCulture.NumberFormat;
             mDateTimeFormat = CultureInfo.InvariantCulture.DateTimeFormat;
-            ValidCommentChars = new[] { '#', ';', '\'' };
+            ValidCommentChars = new[] { '#', ';' };
             mPreferredCommentChar = '#';
             mArrayElementSeparator = ',';


Version working using 7z

Version working using 7z

--- SignNuGetBinaries/Program.cs
+++ SignNuGetBinaries/Program.cs
@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.IO;
 using System.IO.Compression;
 using System.Threading.Tasks;
@@ -101,7 +102,27 @@
                         Console.WriteLine("Building signed NuGet package " + packageName);

                         var signedPackageFile = Path.Combine(outputPath, packageName);
-                        ZipFile.CreateFromDirectory(target, signedPackageFile);
+                        //ZipFile giving a strange bug - shell out to 7z for now
+                        //ZipFile.CreateFromDirectory(target, signedPackageFile);
+                        ZipArchive
+                        // Hack in 7z call
+                        Process zip = new Process();
+                        zip.StartInfo.WorkingDirectory = target;
+                        zip.StartInfo.FileName = @"C:\Program Files\7-Zip\7z.exe";
+                        zip.StartInfo.UseShellExecute = false;
+                        zip.StartInfo.RedirectStandardError = false;
+                        zip.StartInfo.RedirectStandardOutput = false;
+                        zip.StartInfo.Arguments = String.Format(@"a -tzip -r {0}.zip ""{1}\*.*""", signedPackageFile, target);
+                        Console.WriteLine(@"""{0}"" {1}", zip.StartInfo.FileName, zip.StartInfo.Arguments);
+                        zip.Start();
+                        zip.WaitForExit();
+                        if (zip.ExitCode != 0)
+                        {
+                            Console.Error.WriteLine("Error: 7z returned {0}", zip.ExitCode);
+                        }
+                        zip.Close();
+                        File.Move(signedPackageFile + ".zip", signedPackageFile);
+
                     }));
                 }
             }


Change DNS.cs to new Expirable behavour

Change DNS.cs to new Expirable behavour

--- DNS.cs
+++ DNS.cs
@@ -32,7 +32,7 @@
             {
                 domainCache.RequestedTimes++;

-                return domainCache.RefreshIfExpired().AnswerRecords;
+                return domainCache.Value.AnswerRecords;
             }
             else
             {
@@ -97,11 +97,7 @@
         private static DnsMessage CacheResolver(DnsClient client, string domain, string cacheName, RecordType type, RecordClass @class)
         {
             Entry domainCache;
-            if (GlobalCache.TryGetValue(cacheName, out domainCache))
-            {
-                domainCache.RefreshIfExpired();
-            }
-            else
+            if (!GlobalCache.TryGetValue(cacheName, out domainCache))
             {
                 Func<DnsMessage> renewer = () => client.Resolve(domain, type, @class);


Added a test to prove all names are unique.

--- sourcetests/DotNetCoreTests.cs
+++ sourcetests/DotNetCoreTests.cs
@@ -59,6 +59,15 @@
         }

         [TestMethod]
+        public void All_Direction_Names_Are_Unique()
+            => CollectionAssert.AllItemsAreUnique(
+                Enumerable.Concat(
+                        Direction.CardinalDirections.Select(d => d.Name).ToArray(),
+                        Direction.IntercardinalDirections.Select(d => d.Name).ToArray())
+                    .Concat(Direction.IntermediateCardinalDirections.Select(d => d.Name).ToArray()).ToArray(), "Duplicate(s) detected.");
+
+
+        [TestMethod]
         public void Cycling_Terminates_Prior_To_Overlap()
             => Assert.AreNotEqual(Direction.CycleClockwise().First(), Direction.CycleClockwise().Last());


Fixed push mistake.

Fixed push mistake.

--- CrowesNest/MainForm.cs
+++ CrowesNest/MainForm.cs
@@ -39,7 +39,7 @@

             if (filter != "All")
             {
-                IEnumerable<HackTool> filteredHackToolList = tools.HackToolList.Where( (tool => tool.Category == filter);
+                IEnumerable<HackTool> filteredHackToolList = tools.HackToolList.Where( (tool => tool.Category == filter));
                 //stringList = filteredStringList.ToList<string>()

                 foreach (HackTool ht in filteredHackToolList)


fix bug

fix bug

--- implementation/src/SSystem.Data/SqlServerDatabaseCreator.cs
+++ implementation/src/SSystem.Data/SqlServerDatabaseCreator.cs
@@ -31,7 +31,7 @@
         public string DataFileInitialSize { get; set; } = "5Mb";
         public string LogFileInitialSize { get; set; } = "2Mb";
         public string LogFileGrowth { get; set; } = "1Mb";
-        public SqlServerDatabaseCreator(string dbName,string dbFileDirectory)
+        public SqlServerDatabaseCreator(string dbName, string dbFileDirectory)
         {
             if (string.IsNullOrEmpty(dbName))
                 throw new ArgumentNullException(nameof(dbName));
@@ -42,12 +42,12 @@
             DbFileDirectory = dbFileDirectory;
         }

-        public void Create(string connectionStringName)
+        public void Create(string connectionString)
         {
             string sqlScript = string.Format(@"create DATABASE {0}
 on primary
 (
-name='{0}_data',
+name='{0}',
 filename='{1}',
 size={2},
 maxsize={3},
@@ -60,10 +60,10 @@
 size={6},
 filegrowth={7}
 )
-", DbName, Path.Combine(DbFileDirectory, string.Format("{0}_data.mdf", DbName)), DataFileInitialSize, MaxSize, FileGrowth,
+", DbName, Path.Combine(DbFileDirectory, string.Format("{0}.mdf", DbName)), DataFileInitialSize, MaxSize, FileGrowth,
 Path.Combine(DbFileDirectory, string.Format("{0}_log.ldf", DbName)), LogFileInitialSize, LogFileGrowth);

-            using (var context = new Database(connectionStringName))
+            using (var context = DatabaseFactory.CreateByConnectionString(connectionString))
             {
                 context.ExecuteNonQuery(sqlScript);
             }


Added support for Get-ItemProperty.

Added support for Get-ItemProperty.

--- NtObjectManager/Provider/NtObjectManagerProvider.cs
+++ NtObjectManager/Provider/NtObjectManagerProvider.cs
@@ -30,7 +30,7 @@
     /// Object manager provider.
     /// </summary>
     [CmdletProvider("NtObjectManager", ProviderCapabilities.ExpandWildcards)]
-    public sealed class NtObjectManagerProvider : NavigationCmdletProvider, ISecurityDescriptorCmdletProvider
+    public sealed class NtObjectManagerProvider : NavigationCmdletProvider, ISecurityDescriptorCmdletProvider, IPropertyCmdletProvider
     {
         private static readonly Dictionary<string, NtDirectoryEntry> _item_cache = new Dictionary<string, NtDirectoryEntry>();

@@ -464,31 +464,10 @@
         /// <param name="path">The drive path.</param>
         protected override void GetItem(string path)
         {
-            if (GetDrive() == null)
-            {
+            NtDirectoryEntry entry = GetItemFromPath(path);
+            if (entry == null)
                 return;
-            }
-
-            string relative_path = GetRelativePath(PSPathToNT(path));
-            using (var dir = GetPathDirectory(relative_path, false))
-            {
-                if (!dir.IsSuccess)
-                    return;
-                if (relative_path.Length == 0)
-                {
-                    WriteItemObject(GetDrive().DirectoryRoot.CreateEntry(relative_path, string.Empty, "Directory"),
-                            NTPathToPS(BuildDrivePath(relative_path)), true);
-                }
-                else
-                {
-                    var dir_info = GetEntry(dir.Result, relative_path);
-                    if (dir_info != null)
-                    {
-                        WriteItemObject(GetDrive().DirectoryRoot.CreateEntry(relative_path, dir_info.Name, dir_info.NtTypeName),
-                            NTPathToPS(BuildDrivePath(relative_path)), dir_info.IsDirectory);
-                    }
-                }
-            }
+            WriteItemObject(entry, NTPathToPS(BuildDrivePath(GetRelativePath(PSPathToNT(path)))), entry.IsDirectory);
         }

         private void AddMatches(NtObjectContainer root, string base_path, IEnumerable<string> remaining, List<string> matches)
@@ -648,5 +627,76 @@
         {
             return new GenericObjectSecurity();
         }
+
+        void IPropertyCmdletProvider.GetProperty(string path, Collection<string> providerSpecificPickList)
+        {
+            NtDirectoryEntry entry = GetItemFromPath(path);
+            if (entry == null)
+                return;
+
+            if (entry is NtKeyEntry key && key.ValueCount > 0)
+            {
+                var patterns = providerSpecificPickList.Select(s => new WildcardPattern(s, WildcardOptions.IgnoreCase)).ToArray();
+
+                foreach (var val in key.Values)
+                {
+                    if (patterns.Length == 0 || patterns.Any(p => p.IsMatch(val.Name)))
+                        WritePropertyObject(val, path);
+                }
+            }
+        }
+
+        object IPropertyCmdletProvider.GetPropertyDynamicParameters(string path, Collection<string> providerSpecificPickList)
+        {
+            return null;
+        }
+
+        void IPropertyCmdletProvider.SetProperty(string path, PSObject propertyValue)
+        {
+            throw new NotImplementedException();
+        }
+
+        object IPropertyCmdletProvider.SetPropertyDynamicParameters(string path, PSObject propertyValue)
+        {
+            throw new NotImplementedException();
+        }
+
+        void IPropertyCmdletProvider.ClearProperty(string path, Collection<string> propertyToClear)
+        {
+            throw new NotImplementedException();
+        }
+
+        object IPropertyCmdletProvider.ClearPropertyDynamicParameters(string path, Collection<string> propertyToClear)
+        {
+            throw new NotImplementedException();
+        }
+
+        private NtDirectoryEntry GetItemFromPath(string path)
+        {
+            if (GetDrive() == null)
+            {
+                return null;
+            }
+
+            string relative_path = GetRelativePath(PSPathToNT(path));
+            using (var dir = GetPathDirectory(relative_path, false))
+            {
+                if (!dir.IsSuccess)
+                    return null;
+                if (relative_path.Length == 0)
+                {
+                    return GetDrive().DirectoryRoot.CreateEntry(relative_path, string.Empty, "Directory");
+                }
+                else
+                {
+                    var dir_info = GetEntry(dir.Result, relative_path);
+                    if (dir_info != null)
+                    {
+                        return GetDrive().DirectoryRoot.CreateEntry(relative_path, dir_info.Name, dir_info.NtTypeName);
+                    }
+                }
+            }
+            return null;
+        }
     }
 }


UnlockForm: accept IEnumerable instead of List

--- OpenSlx.Lib/Web/Extensions/UserControlExtensions.cs
+++ OpenSlx.Lib/Web/Extensions/UserControlExtensions.cs
@@ -113,7 +113,7 @@
         /// </summary>
         /// <param name="parent"></param>
         /// <param name="controlIds"></param>
-        public static void UnlockForm(this Control parent, List<String> controlIds)
+        public static void UnlockForm(this Control parent, IEnumerable<String> controlIds)
         {
             foreach (String id in controlIds)
             {


Purple Goodness v1.5.7

Purple Goodness v1.5.7

--- IRCTerraria/Indigoirc.cs
+++ IRCTerraria/Indigoirc.cs
@@ -56,7 +56,7 @@

         public override Version Version
         {
-            get { return new Version("1.5.6"); }
+            get { return new Version("1.5.7"); }
         }
         public override string Name
         {
@@ -173,9 +173,9 @@
                             if (splitInput[3].Equals(":.list"))
                             {
                                 //TSPlayer player = TShock.Players[args.Who];
-                                TSPlayer[] players = TShock.Players;

-                                if (players[0] != null)
+
+                                if (Players.Count > 0)
                                 {
                                    // Console.WriteLine(players[0].Name);

@@ -202,6 +202,7 @@
                                 }
                                 else
                                 {
+                                    //Console.WriteLine("Detected no one online");
                                     playerList = "Online (0/" + TShock.Config.MaxSlots + "): ";
                                 }
                                 writer.WriteLine("PRIVMSG " + channel + " :" + playerList);
@@ -251,7 +252,41 @@
                                     Chat(Color.LightPink, message);
                                 }
                             }
-
+
+
+                        }
+                        else if (splitInput[1].Equals("JOIN"))
+                        {
+                            int loc = splitInput[0].IndexOf("!");
+                                //Console.WriteLine("Location of \"!~\": " + loc);
+                                //Console.WriteLine(splitInput[0]);
+                            if (loc > 0)
+                            {
+                                splitInput[0] = splitInput[0].Substring(0, loc);
+                                splitInput[0] = ReplaceFirst(splitInput[0], ":", "");
+                                Console.WriteLine(splitInput[0]);
+                            }
+                            //Console.WriteLine(nick);
+                            if (!splitInput[0].Equals(nick))
+                            {
+                                Chat(Color.LightPink, "[IRC] " + splitInput[0] + " joined the channel.");
+                            }
+                        }
+                        else if (splitInput[1].Equals("QUIT"))
+                        {
+                            int loc = splitInput[0].IndexOf("!");
+                            //Console.WriteLine("Location of \"!~\": " + loc);
+
+                            if (loc > 0)
+                            {
+                                splitInput[0] = splitInput[0].Substring(0, loc);
+                                splitInput[0] = ReplaceFirst(splitInput[0], ":", "");
+                                //Console.WriteLine(splitInput[0]);
+                            }
+                            if (!splitInput[0].Equals(nick))
+                            {
+                                Chat(Color.LightPink, "[IRC] " + splitInput[0] + " left the channel.");
+                            }
                         }
                         else
                         {
@@ -476,7 +511,7 @@
             double initSeconds = this.initTime.TotalSeconds;
             double finalSeconds = currentTime.TotalSeconds;
             double remainingSeconds = finalSeconds - initSeconds;
-            Console.WriteLine(finalSeconds + " - " + initSeconds + " = " + remainingSeconds);
+            //Console.WriteLine(finalSeconds + " - " + initSeconds + " = " + remainingSeconds);
             TimeSpan remainingTime = TimeSpan.FromSeconds(finalSeconds - initSeconds);


Fixes issue #846 IndexOutOfRangeException when reading empty icon from registry in ControlPanel plugin

--- Plugins/Wox.Plugin.ControlPanel/ControlPanelList.cs
+++ Plugins/Wox.Plugin.ControlPanel/ControlPanelList.cs
@@ -230,6 +230,12 @@
                 if (currentKey.OpenSubKey("DefaultIcon").GetValue(null) != null)
                 {
                     iconString = new List<string>(currentKey.OpenSubKey("DefaultIcon").GetValue(null).ToString().Split(new[] { ',' }, 2));
+                    if (string.IsNullOrEmpty(iconString[0]))
+                    {
+                        // fallback to default icon
+                        return null;
+                    }
+
                     if (iconString[0][0] == '@')
                     {
                         iconString[0] = iconString[0].Substring(1);


use the actual recent activity udf

use the actual recent activity udf

--- Purchasing.Mvc/Controllers/HistoryAjaxController.cs
+++ Purchasing.Mvc/Controllers/HistoryAjaxController.cs
@@ -36,7 +36,7 @@
             using (var conn = _dbService.GetConnection())
             {
                 var lastOrderEvent = conn.Query<OrderTrackingHistory>(
-                    "SELECT * FROM [dbo].[udf_GetPendingOrdersForLogin] (@login) ORDER BY lastactiondate DESC",
+                    "SELECT * FROM [dbo].[udf_GetRecentActivityForLogin] (@login)",
                     new {login = CurrentUser.Identity.Name}).FirstOrDefault();

                 return PartialView(lastOrderEvent);


more tests

more tests

--- Reusable.Tests/src/Core/DuckEqualityComparerTest.cs
+++ Reusable.Tests/src/Core/DuckEqualityComparerTest.cs
@@ -16,7 +16,7 @@
     public class DuckEqualityComparerTest
     {
         [TestMethod]
-        public void Equals_CanCompareTowNamedTypes()
+        public void Equals_CanCompareTwoNamedTypes()
         {
             var p0 = new PersonLib1 { FirstName = "John", LastName = "Doe" };
             var p1 = new PersonLib1 { FirstName = "John", LastName = "Doe" };
@@ -40,6 +40,26 @@
             IsFalse(comparer.Equals(p1, p3));
             IsFalse(comparer.Equals(p3, p1));
             IsFalse(comparer.Equals(p1, p4));
+        }
+
+        [TestMethod]
+        public void Equals_DisallowsToCompareSameTypes()
+        {
+            var p0 = new PersonLib1 { FirstName = "John", LastName = "Doe" };
+            var p1 = new PersonLib1 { FirstName = "John", LastName = "Doe" };
+            var p2 = new PersonLib2 { FirstName = "JOHN", LastName = "Doe" };
+            var p3 = new PersonLib2 { FirstName = "Joh", LastName = "Doe" };
+            var p4 = new PersonLib2 { FirstName = default, LastName = "Doe" };
+
+            var comparer =
+                new DuckEqualityComparerBuilder<PersonLib1, PersonLib1>()
+                    .Compare(x => x.FirstName, y => y.FirstName, StringComparer.OrdinalIgnoreCase)
+                    .Compare(x => x.LastName, y => y.LastName, StringComparer.OrdinalIgnoreCase)
+                    .Build();
+
+            //IsTrue(comparer.Equals(p0, p1));
+            IsTrue(comparer.Equals(p1, p1));
+            IsTrue(comparer.Equals(p2, p2));
         }

         [TestMethod]
@@ -55,15 +75,19 @@
                     .Compare(x => x.LastName1, y => y.LastName2, StringComparer.OrdinalIgnoreCase)
                     .Build();

-            IsTrue(comparer.Equals(
-                new { FirstName1 = "John", LastName1 = "Doe" },
-                new { FirstName2 = "JOHN", LastName2 = "DOE" }
-            ));
-
-            IsFalse(comparer.Equals(
-                new { FirstName1 = "Johny", LastName1 = "Dope" },
-                new { FirstName2 = "JOHN", LastName2 = "DOE" }
-            ));
+            IsTrue(
+                comparer.Equals(
+                    new { FirstName1 = "John", LastName1 = "Doe" },
+                    new { FirstName2 = "JOHN", LastName2 = "DOE" }
+                )
+            );
+
+            IsFalse(
+                comparer.Equals(
+                    new { FirstName1 = "Johny", LastName1 = "Dope" },
+                    new { FirstName2 = "JOHN", LastName2 = "DOE" }
+                )
+            );
         }

         [TestMethod]
@@ -79,22 +103,26 @@
                     .Compare(x => x.LastName, y => y.LastName2, StringComparer.OrdinalIgnoreCase)
                     .Build();

-            IsTrue(comparer.Equals(
-                new PersonLib1 { FirstName = "John", LastName = "Doe" },
-                new { FirstName2 = "JOHN", LastName2 = "DOE" }
-            ));
-
-            IsFalse(comparer.Equals(
-                new PersonLib1 { FirstName = "Johny", LastName = "Dope" },
-                new { FirstName2 = "JOHN", LastName2 = "DOE" }
-            ));
-        }
-
-        [TestMethod]
-        public void Equals_CanCompareWithCustomEquals()
-        {
-            var comparer =
-                new DuckEqualityComparerBuilder<PersonLib1, PersonLib2>()
+            IsTrue(
+                comparer.Equals(
+                    new PersonLib1 { FirstName = "John", LastName = "Doe" },
+                    new { FirstName2 = "JOHN", LastName2 = "DOE" }
+                )
+            );
+
+            IsFalse(
+                comparer.Equals(
+                    new PersonLib1 { FirstName = "Johny", LastName = "Dope" },
+                    new { FirstName2 = "JOHN", LastName2 = "DOE" }
+                )
+            );
+        }
+
+        [TestMethod]
+        public void Equals_CanCompareWithCustomEqualsAndIsNotCommutative()
+        {
+            var comparer =
+                new DuckEqualityComparerBuilder<PersonLib1, PersonLib2>(Commutativity.Disable)
                     .Compare(x => x.FirstName, y => y.FirstName, (x, y) => x.StartsWith(y, StringComparison.OrdinalIgnoreCase))
                     .Compare(x => x.LastName, y => y.LastName, (x, y) => x.EndsWith(y, StringComparison.OrdinalIgnoreCase))
                     .Build();
@@ -108,11 +136,10 @@
             IsTrue(comparer.Equals(p2, p2));

             IsTrue(comparer.Equals(p1, p2));
-            IsTrue(comparer.Equals(p2, p1));
-
             IsTrue(comparer.Equals(p1, p3));
-            IsTrue(comparer.Equals(p3, p1));
             IsFalse(comparer.Equals(p1, p4));
+
+            ThrowsException<ArgumentException>(() => comparer.Equals(p2, p1));
         }
     }

@@ -123,16 +150,18 @@

     public class DuckEqualityComparerBuilder<TX, TY>
     {
-        private readonly ParameterExpression _parameterX = Expression.Parameter(typeof(TX), "x");
-        private readonly ParameterExpression _parameterY = Expression.Parameter(typeof(TY), "y");
+        private readonly Commutativity _commutativity;
+        private readonly ParameterExpression _parameterX = Expression.Parameter(typeof(TX), "param_x");
+        private readonly ParameterExpression _parameterY = Expression.Parameter(typeof(TY), "param_y");

         private readonly IList<(Expression equals, Expression getHashCodeX, Expression getHashCodeY)> _expressions = new List<(Expression, Expression, Expression)>();

-        public DuckEqualityComparerBuilder<TX, TY> Compare<T>(
-            Expression<Func<TX, T>> getValueX,
-            Expression<Func<TY, T>> getValueY,
-            IEqualityComparer<T> comparer = null
-        )
+        public DuckEqualityComparerBuilder(Commutativity commutativity = Commutativity.Enable)
+        {
+            _commutativity = commutativity;
+        }
+
+        public DuckEqualityComparerBuilder<TX, TY> Compare<T>(Expression<Func<TX, T>> getValueX, Expression<Func<TY, T>> getValueY, IEqualityComparer<T> comparer = null)
         {
             comparer = comparer ?? EqualityComparer<T>.Default;

@@ -166,48 +195,44 @@
             return this;
         }

-        public DuckEqualityComparerBuilder<TX, TY> Compare<T>(
-            Expression<Func<TX, T>> getValueX,
-            Expression<Func<TY, T>> getValueY,
-            Expression<Func<T, T, bool>> equals
-        )
+        public DuckEqualityComparerBuilder<TX, TY> Compare<T>(Expression<Func<TX, T>> getValueX, Expression<Func<TY, T>> getValueY, Expression<Func<T, T, bool>> equals)
         {
             var label = Expression.Label(typeof(bool));

-            var variableX = Expression.Variable(typeof(T), "valueX");
-            var variableY = Expression.Variable(typeof(T), "valueY");
+            var variableX = Expression.Variable(typeof(T), "var_x");
+            var variableY = Expression.Variable(typeof(T), "var_y");
+
+            // We need to protect the custom equality-check from null.
+            var referenceEquals = (Expression<Func<T, bool>>)(obj => ReferenceEquals(obj, null));

             var equals_ =
                 Expression.Block(
                     new[] { variableX, variableY },
+                    // x = getValueX(TX);
                     Expression.Assign(variableX, Expression.Invoke(getValueX, _parameterX)),
+                    // y = getValueX(TY);
                     Expression.Assign(variableY, Expression.Invoke(getValueY, _parameterY)),
+                    // if (ReferenceEquals(x, null) return false;
                     Expression.IfThen(
-                        test: Expression.OrElse(
-                            Expression.IsTrue(Expression.Equal(variableX, Expression.Constant(null))),
-                            Expression.IsTrue(Expression.Equal(variableY, Expression.Constant(null)))
-                        ),
-                        ifTrue: Expression.Return(label, Expression.Invoke((Expression<Func<T, T, bool>>)((x, y) => false), variableX, variableY))
+                        test: Expression.IsTrue(Expression.Invoke(referenceEquals, variableX)),
+                        ifTrue: Expression.Return(label, Expression.Constant(false))
                     ),
+                    // if (ReferenceEquals(y, null) return false;
+                    Expression.IfThen(
+                        test: Expression.IsTrue(Expression.Invoke(referenceEquals, variableY)),
+                        ifTrue: Expression.Return(label, Expression.Constant(false))
+                    ),
+                    // return equals(x, y)
                     Expression.Return(label, Expression.Invoke(equals, variableX, variableY)),
+
+                    // This makes the compiler happy.
                     Expression.Label(label, Expression.Constant(false))
                 );

-            // comparer.GetHashCode(getValueX(x))
-            var getHashCodeFunc = (Expression<Func<T, int>>)(obj => 0);
-
-            var getHashCodeX =
-                Expression.Invoke(
-                    getHashCodeFunc,
-                    Expression.Invoke(getValueX, _parameterX)
-                );
-
-            // comparer.GetHashCode(getValueY(y))
-            var getHashCodeY =
-                Expression.Invoke(
-                    getHashCodeFunc,
-                    Expression.Invoke(getValueY, _parameterY)
-                );
+            // With a custom Equals we probably cannot GetHashCode anyway so just skip it.
+            // return 0;
+            var getHashCodeX = Expression.Constant(0);
+            var getHashCodeY = Expression.Constant(0);

             _expressions.Add((equals_, getHashCodeX, getHashCodeY));

@@ -216,22 +241,20 @@

         public EqualityComparer<object> Build()
         {
-            var equalityComparer = _expressions.Aggregate((next, current) =>
-            (
-                equals: ConcatenateEqualsExpressions(current.equals, next.equals),
-                getHashCodeX: ConcatenateGetHashCodeExpressions(current.getHashCodeX, next.getHashCodeX),
-                getHashCodeY: ConcatenateGetHashCodeExpressions(current.getHashCodeY, next.getHashCodeY)
-            ));
+            var equalityComparer = _expressions.Aggregate(
+                (next, current) =>
+                (
+                    equals: ConcatenateEqualsExpressions(current.equals, next.equals),
+                    getHashCodeX: ConcatenateGetHashCodeExpressions(current.getHashCodeX, next.getHashCodeX),
+                    getHashCodeY: ConcatenateGetHashCodeExpressions(current.getHashCodeY, next.getHashCodeY)
+                )
+            );

             var equalsFunc = Expression.Lambda<Func<TX, TY, bool>>(equalityComparer.equals, new[] { _parameterX, _parameterY }).Compile();
             var getHashCodeXFunc = Expression.Lambda<Func<TX, int>>(equalityComparer.getHashCodeX, _parameterX).Compile();
             var getHashCodeYFunc = Expression.Lambda<Func<TY, int>>(equalityComparer.getHashCodeY, _parameterY).Compile();

-            return DuckEqualityComparer<TX, TY>.Create(
-                equalsFunc,
-                getHashCodeXFunc,
-                getHashCodeYFunc
-            );
+            return DuckEqualityComparer<TX, TY>.Create(equalsFunc, getHashCodeXFunc, getHashCodeYFunc, _commutativity);
         }

         public static implicit operator EqualityComparer<object>(DuckEqualityComparerBuilder<TX, TY> builder) => builder.Build();
@@ -249,18 +272,24 @@
                 );
         }

-        public static Expression ConcatenateGetHashCodeExpressions(Expression getHashCodeExpressionX, Expression getHashCodeExpressionY)
+        public static Expression ConcatenateGetHashCodeExpressions(Expression getHashCodeX, Expression getHashCodeY)
         {
             // x * 31 + y
             return
                 Expression.Add(
                     Expression.Multiply(
-                        getHashCodeExpressionX,
+                        getHashCodeX,
                         Expression.Constant(31)
                     ),
-                    getHashCodeExpressionY
-                );
-        }
+                    getHashCodeY
+                );
+        }
+    }
+
+    public enum Commutativity
+    {
+        Enable,
+        Disable
     }

     public class DuckEqualityComparer<TX, TY> : EqualityComparer<object>
@@ -268,14 +297,14 @@
         private readonly Func<TX, TY, bool> _equals;
         private readonly Func<TX, int> _getHashCodeX;
         private readonly Func<TY, int> _getHashCodeY;
-        private readonly bool _isCommutative;
-
-        private DuckEqualityComparer(Func<TX, TY, bool> equals, Func<TX, int> getHashCodeX, Func<TY, int> getHashCodeY, bool isCommutative = true)
+        private readonly Commutativity _commutativity;
+
+        private DuckEqualityComparer(Func<TX, TY, bool> equals, Func<TX, int> getHashCodeX, Func<TY, int> getHashCodeY, Commutativity commutativity)
         {
             _equals = equals;
             _getHashCodeX = getHashCodeX;
             _getHashCodeY = getHashCodeY;
-            _isCommutative = isCommutative;
+            _commutativity = commutativity;
         }

         public override bool Equals(object x, object y)
@@ -287,11 +316,15 @@
             ValidateType(x);
             ValidateType(y);

+            if (_commutativity == Commutativity.Disable)
+            {
+                if (!(x is TX && y is TY))
+                {
+                    throw new ArgumentException($"This comparer is not commutative. You have to specify parameters in the following order: {typeof(TX).Name} then {typeof(TY).Name}.");
+                }
+            }
+
             if (Equals((x, y))) return true;
-            if (_isCommutative)
-            {
-                if (Equals((y, x))) return true;
-            }

             return false;
         }
@@ -314,17 +347,19 @@
         }

         [NotNull]
-        public static EqualityComparer<object> Create(
+        public static EqualityComparer<object> Create
+        (
             [NotNull] Func<TX, TY, bool> equals,
             [NotNull] Func<TX, int> getHashCodeX,
-            [NotNull] Func<TY, int> getHashCodeY
+            [NotNull] Func<TY, int> getHashCodeY,
+            Commutativity commutativity = Commutativity.Enable
         )
         {
             if (equals == null) throw new ArgumentNullException(nameof(equals));
             if (getHashCodeX == null) throw new ArgumentNullException(nameof(getHashCodeX));
             if (getHashCodeY == null) throw new ArgumentNullException(nameof(getHashCodeY));

-            return new DuckEqualityComparer<TX, TY>(equals, getHashCodeX, getHashCodeY);
+            return new DuckEqualityComparer<TX, TY>(equals, getHashCodeX, getHashCodeY, commutativity);
         }

         private static void ValidateType(object obj)


EditTimeEntryVC: fix typo

EditTimeEntryVC: fix typo

--- Ross/ViewControllers/EditTimeEntryViewController.cs
+++ Ross/ViewControllers/EditTimeEntryViewController.cs
@@ -60,7 +60,7 @@
         private int autoCommitId;
         private bool shouldRebindOnAppear;
         private UITableView autoCompletionTableView;
-        private UIBarButtonItem autoCopmletionDoneBarButtonItem;
+        private UIBarButtonItem autoCompletionDoneBarButtonItem;

         public EditTimeEntryViewController (TimeEntryModel model)
         {
@@ -303,18 +303,18 @@

         private void BindAutoCompletionDoneBarButtonItem (UINavigationItem v)
         {
-            autoCopmletionDoneBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Done);
-            autoCopmletionDoneBarButtonItem.Clicked += (object sender, EventArgs e) => {
+            autoCompletionDoneBarButtonItem = new UIBarButtonItem (UIBarButtonSystemItem.Done);
+            autoCompletionDoneBarButtonItem.Clicked += (object sender, EventArgs e) => {
                 DescriptionSuggestionsMode = false;
             };
-            v.SetRightBarButtonItem (autoCopmletionDoneBarButtonItem, true);
+            v.SetRightBarButtonItem (autoCompletionDoneBarButtonItem, true);
         }

         private void UnBindAutoCompletionDoneBarButtonItem (UINavigationItem v)
         {
-            if (v.RightBarButtonItem == autoCopmletionDoneBarButtonItem) {
+            if (v.RightBarButtonItem == autoCompletionDoneBarButtonItem) {
                 v.SetRightBarButtonItem (null, true);
-                autoCopmletionDoneBarButtonItem = null;
+                autoCompletionDoneBarButtonItem = null;
             }
         }


[Inspector] Remove space

[Inspector] Remove space

--- Editor/LoggerEditor.cs
+++ Editor/LoggerEditor.cs
@@ -46,9 +46,6 @@

             DrawEnableOnPlayToggle();
             DrawClearOnPlayToggle();
-
-            EditorGUILayout.Space();
-
             DrawLogInRealTimeToggle();
             DrawAppendToggle();
             DrawEchoToConsoleToggle();


Update WoodenPc.cs

Update WoodenPc.cs

--- SStandalones/SMiscs/SWoodenPcMisc/Miscs/WoodenPc.cs
+++ SStandalones/SMiscs/SWoodenPcMisc/Miscs/WoodenPc.cs
@@ -25,6 +25,7 @@
         private Notification notificationRemaining = null;
         private long ms = -1;
         private DrawingDraw drawingEvent = null;
+        private int delay = 420;

         public WoodenPc()
         {
@@ -120,9 +121,8 @@
                     ms = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;
                     drawingEvent = delegate
                     {
-                        if (!packetSent && (ms + (250 * 1000)) < (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond))
+                        if (!packetSent && (ms + (delay * 1000)) < (DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond))
                         {
-                            Console.WriteLine((ms + (250 * 1000)) + " " + DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond);
                             Game.SendPacket(packet.ToArray(), PacketChannel.C2S, PacketProtocolFlags.Reliable);
                             packetSent = true;
                             if (notification != null)
@@ -145,13 +145,13 @@
                                 notificationRemaining =
                                 Common.ShowNotification(
                                     "Remaining: " +
-                                    (ms + (250 * 1000) - DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond).ToString(),
-                                    Color.YellowGreen, 250 * 1000);
+                                    (ms + (delay * 1000) - DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond).ToString(),
+                                    Color.YellowGreen, delay * 1000);
                             }
                             else
                             {
                                 notificationRemaining.Text = "Remaining: " +
-                                    ((ms + (250 * 1000) - DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) / 1000).ToString() + "s";
+                                    ((ms + (delay * 1000) - DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond) / 1000).ToString() + "s";
                             }
                         }
                     };


Added Support for Entity Reference Collections and Option Set Values

--- DLaB.Xrm/Extensions.cs
+++ DLaB.Xrm/Extensions.cs
@@ -1731,8 +1731,10 @@
                 {
                     var entity = param.Value as Entity;
                     var entityRef = param.Value as EntityReference;
+                    var entityRefCollection = param.Value as EntityReferenceCollection;
                     var enumerable = param.Value as IEnumerable;
                     var entities = param.Value as EntityCollection;
+                    var optionSet = param.Value as OptionSetValue;
                     if (entity != null)
                     {
                         values.Add(entity.ToStringAttributes(GenerateNonBreakingSpace(4) + "Param[" + param.Key + "][{0}]: {1}"));
@@ -1746,10 +1748,19 @@
                         values.Add(GenerateNonBreakingSpace(4) + "Param[" + param.Key + "] Entity Collection " + entities.EntityName + ":");
                         values.AddRange(entities.Entities.Select(i => GenerateNonBreakingSpace(8) + i.ToStringAttributes()));
                     }
+                    else if (entityRefCollection != null)
+                    {
+                        values.Add(GenerateNonBreakingSpace(4) + "Param[" + param.Key + "] Entity Reference Collection:");
+                        values.AddRange(entityRefCollection.Select(i => GenerateNonBreakingSpace(8) + i.ToStringDebug()));
+                    }
                     else if (enumerable != null && !(param.Value is String))
                     {
-                        values.Add(GenerateNonBreakingSpace(4) + "Param[" + param.Key + "]: " + param.GetType().FullName + ":");
+                        values.Add(GenerateNonBreakingSpace(4) + "Param[" + param.Key + "]: " + param.Value.GetType().FullName + ":");
                         values.AddRange(from object item in enumerable select GenerateNonBreakingSpace(8) + item);
+                    }
+                    else if (optionSet != null)
+                    {
+                        values.Add(GenerateNonBreakingSpace(4) + "Param[" + param.Key + "]: " + optionSet.Value);
                     }
                     else
                     {


SecoundHomeWork

SecoundHomeWork

--- ClickElement.cs
+++ ClickElement.cs
@@ -9,10 +9,7 @@
 {
     class ClickElement
     {
-        public ClickElement()
-        {
-            //_driver = WebDriver.ManageWebDriverInstance;
-        }
+        public ClickElement() {}

         public void click(IWebElement elementToClick)
         {


Added a description for the CacheLoader class.

--- src/base/common/cache/CacheLoader.cs
+++ src/base/common/cache/CacheLoader.cs
@@ -4,6 +4,12 @@

 namespace Nohros.Caching
 {
+  /// <summary>
+  /// Computes an retrieve values, based on a key, for use in populating a
+  /// <see cref="Cache{T}"/>
+  /// </summary>
+  /// <typeparam name="T">The type of the objects that is stored loaded.
+  /// </typeparam>
   public abstract partial class CacheLoader<T>
   {
     /// <summary>
@@ -19,7 +25,8 @@
     }

     /// <summary>
-    /// Computes or retrieves the value correspnoding to <paramref name="key"/>.
+    /// Computes or retrieves the value correspnoding to
+    /// <paramref name="key"/>.
     /// </summary>
     /// <param name="key">The key whose value should be loaded; will never
     /// be null.</param>


代替LUTがない時の修正

代替LUTがない時の修正

--- ColorGrading.cs
+++ ColorGrading.cs
@@ -55,12 +55,14 @@
         protected virtual void UpdateLUT() {
             try {
                 var path = GetImagePath();
-                var next = (File.Exists (path) ? LoadTypeEnum.ImageFile : LoadTypeEnum.Texture);
+                var next = (File.Exists (path) ? LoadTypeEnum.ImageFile :
+                    (data.alternativeImage != null ? LoadTypeEnum.Texture : LoadTypeEnum.None));

                 switch (next) {
                 case LoadTypeEnum.ImageFile:
                     var writeTime = File.GetLastWriteTime (path);
                     if (writeTime != _lastUpdateTime) {
+                        Debug.LogFormat("Load image from {0}", path);
                         _lastUpdateTime = writeTime;
                         LoadImage (path);
                         UpdateLUT (_lutImage);
@@ -68,10 +70,11 @@
                     break;
                 case LoadTypeEnum.Texture:
                     ReleaseImageTex();
-                    if (current != LoadTypeEnum.Texture && data.alternativeImage != null) {
-                        Debug.Log("Update LUT");
+                    if (current != LoadTypeEnum.Texture && data.alternativeImage != null)
                         UpdateLUT(data.alternativeImage);
-                    }
+                    break;
+                default:
+                    ReleaseImageTex();
                     break;
                 }


Don't add empty 'extra' fields to chat msg JSON

--- source/Craft.Net.Networking/ChatTransciever.cs
+++ source/Craft.Net.Networking/ChatTransciever.cs
@@ -233,15 +233,21 @@
         public JObject AsJObject()
         {
             JObject self = new JObject();
-            var extras = new JArray();
+            JArray extras = null;
             if (SubMessages != null)
             {
+                extras = new JArray();
+
                 foreach (ChatMessage c in SubMessages)
                 {
                     extras.Add(c.AsJObject());
                 }
             }
-            self.Add(new JProperty("extra", extras));
+            // 'extra' may not be empty if it is present.
+            if (extras != null)
+            {
+                self.Add(new JProperty("extra", extras));
+            }
             self.Add(new JProperty("text", this.Text));
             self.Add(new JProperty("bold", this.Bold));
             self.Add(new JProperty("strikethrough", this.StrikeThrough));