﻿<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text" xml:lang="en">MfGames .NET Libraries</title>
  <link type="application/atom+xml" href="https://mfgames.com/mfgames-cil/atom.xml" rel="self" />
  <link type="text/html" href="https://mfgames.com/mfgames-cil/" rel="alternate" />
  <updated>2026-10-04T17:37:30Z</updated>
  <id>https://mfgames.com/mfgames-cil/</id>
  <author>
    <name>D. Moonfire</name>
  </author>
  <rights>Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International</rights>
  <entry>
    <title>Renaming MfGames.Crypto to MfGames.Cryptography (MfGames .NET Libraries)</title>
    <link rel="alternate" href="https://mfgames.com/blog/2024/04/21/renaming-mfgames-crypto/" />
    <updated>2024-04-21T05:00:00Z</updated>
    <id>https://mfgames.com/blog/2024/04/21/renaming-mfgames-crypto/</id>
    <category term="mfgames-net-libraries" scheme="https://mfgames.com/categories/" label="MfGames .NET Libraries" />
    <content type="html">&lt;p&gt;For many years, &amp;ldquo;crypto&amp;rdquo; really meant only one thing in the programming world: cryptozoology. No, actually &amp;ldquo;cryptography.&amp;rdquo; However, with the advent of web3 and cryptocurrencies, the world &amp;ldquo;crypto&amp;rdquo; is becoming muddled and no-longer obvious of its purpose.&lt;/p&gt;
&lt;p&gt;Recently, &lt;a href="https://www.bouncycastle.org/"&gt;BouncyCastle&lt;/a&gt; has gone through a little refactoring themselves after starting with &lt;code&gt;BouncyCastle&lt;/code&gt; then renaming themselves to &lt;code&gt;Portable.BouncyCastle&lt;/code&gt; and finally &lt;code&gt;BouncyCastle.Cryptography&lt;/code&gt;. Overally, we like the final name and it was inspiration for us doing the same.&lt;/p&gt;
&lt;p&gt;So, it isn't really marked as a &amp;ldquo;breaking&amp;rdquo; change, but &lt;code&gt;MfGames.Crypto&lt;/code&gt; is being renamed to &lt;code&gt;MfGames.Cryptography&lt;/code&gt;. And, to avoid the struggle we had with BouncyCastle, the namespace also was changed to reflect that change.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Create iCalendar Files with Nitride (MfGames .NET Libraries)</title>
    <link rel="alternate" href="https://mfgames.com/blog/2024/06/01/nitride-icalendar/" />
    <updated>2024-06-01T05:00:00Z</updated>
    <id>https://mfgames.com/blog/2024/06/01/nitride-icalendar/</id>
    <category term="mfgames-net-libraries" scheme="https://mfgames.com/categories/" label="MfGames .NET Libraries" />
    <content type="html">&lt;p&gt;One of the more useful features in previous versions of &lt;a href="//d.moonfire.us"&gt;Dylan's&lt;/a&gt; static site generators was the ability to create an iCalendar file of the posts, both past and future. It wasn't only just to see little entries pop up for the dopamine rush, but also to give them a head's up when a new chapter for &lt;a href="//fedran.com"&gt;Fedran&lt;/a&gt; needs to be written or its been a few months since a blog post has been written.&lt;/p&gt;
&lt;p&gt;We use iCalendar because it's a solid standard format that can easily be added into Nextcloud, put on a phone, or otherwise used anywhere to keep it in mind.&lt;/p&gt;
&lt;p&gt;(Technicaly, it could also be used to create task lists for sites that are missing links or other things but out of scope for this iteration).&lt;/p&gt;
&lt;p&gt;We put this into the &lt;code&gt;MfGames.Nitride.Temporal&lt;/code&gt; even though it adds an extra dependency (&lt;a href="https://github.com/rianjs/ical.net"&gt;Ical.Net&lt;/a&gt;) because it is a relatively small feature and it hit that ratio of package management verses three additional classes. Like the rest of the temporal packages, this built to use &lt;a href="https://nodatime.org/"&gt;Noda.Time&lt;/a&gt; for coordinating times.&lt;/p&gt;
&lt;p&gt;The &lt;a href="//mfgames.com/mfgames-cil/docs/nitride/temporal/"&gt;documentation&lt;/a&gt; has some notes on how to include and use it inside a Nitride project.&lt;/p&gt;
&lt;h2&gt;New Entity Constructor&lt;/h2&gt;
&lt;p&gt;We also added new constructor to &lt;code&gt;MfGames.Gallium.Entity&lt;/code&gt; that allows multiple components to be set as part of the constructor.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// These are all the same.
var entity1 = new Entity();
entity1 = entity1.Add(&amp;quot;bob&amp;quot;);
entity1 = entity1.Add(13);

var entity2 = new Entity().Add(&amp;quot;bob&amp;quot;).Add(13);

var entity3 = new Entity().SetAll(&amp;quot;bob&amp;quot;, 13);

// These are the new features.
var entity4 = new Entity(&amp;quot;bob&amp;quot;, 13);

var entity5 = new Entity(13, &amp;quot;bob&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It seemed like a no-brainer, mainly because it is a pattern we use a lot in the code, but Dylan finds that the formatting is less than &amp;ldquo;pretty&amp;rdquo; when it comes to multi-line chaining operations.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;var notPretty = new Entity(
    &amp;quot;bob&amp;quot;,
    13,
    instant,
    path)
    .AddTextContent(content);

var pretty = new Entity()
    .SetAll(
        &amp;quot;bob&amp;quot;,
        13,
        instant,
        path)
    .AddTextContent(content);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Either work though, so it will end up reducing some of the clutter for common use cases.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Deprecations and Updates (MfGames .NET Libraries)</title>
    <link rel="alternate" href="https://mfgames.com/blog/2026/07/04/deprecations-and-updates/" />
    <updated>2026-07-04T05:00:00Z</updated>
    <id>https://mfgames.com/blog/2026/07/04/deprecations-and-updates/</id>
    <category term="mfgames-net-libraries" scheme="https://mfgames.com/categories/" label="MfGames .NET Libraries" />
    <content type="html">&lt;p&gt;It's been a while, but we had a productive week making changes to the library.&lt;/p&gt;
&lt;h2&gt;Deprecations&lt;/h2&gt;
&lt;p&gt;One advantage of having a monorepo of all of the &lt;a href="//mfgames.com/mfgames-cil/"&gt;MfGames&lt;/a&gt; packages is being able to link everything together without doing a railcar shuffle when one package requires another and another and takes half a day to update a dependency. The drawback is that it makes it harder to abandon one of the libraries. Today is one of those days where we realize there are three libraries that need to be dropped from active development.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MfGames.Identifiers&lt;/code&gt; was a good idea at the time but then we found that &lt;a href="//d.moonfire.us/blog/2026/01/04/other-smarter-people/"&gt;other libraries can handle the same goals&lt;/a&gt; and we don't have to maintain ours. Also, working with source generated files is painful so we are thinking those libraries are a better choice for now.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MfGames.Nitride.SpectreConsole&lt;/code&gt; was an attempt to funnel Serilog output through SprectreConsole so we could get progress bars playing well with output for &lt;code&gt;MfGames.Nitride&lt;/code&gt;. It ended up being cumbersome and, while it worked, it also had some minor quirks that were irriating enough that we just gave up on the idea of progress bars entirely instead of trying to fix it.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MfGames.Serilog.SpectreExpressions&lt;/code&gt; was the underlying library for the &lt;code&gt;MfGames.Nitride.SpectreConsole&lt;/code&gt;. This ended up being a mirror of the existing expressions library from Serilog because the original was sealed and couldn't be extended without copying the wheel. It also didn't have the full ability as the original library because it was hard to maintain code that isn't ours while needing to track any vendor changes. So when &lt;code&gt;MfGames.Nitride.SpectreConsole&lt;/code&gt; was deprecated, so was this.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, we don't want to abandon old code entirely, so we moved those projects from the &lt;code&gt;//src&lt;/code&gt; directory into the &lt;code&gt;//attic/&lt;/code&gt; directory. That way, the code remains available in case we find another use of that. This also means that those projects will &amp;ldquo;bit rot&amp;rdquo; in that they won't be refactored and maintained with the code in &lt;code&gt;//src/&lt;/code&gt;, &lt;code&gt;//tests/&lt;/code&gt;, and &lt;code&gt;//examples/&lt;/code&gt;. The more time passes on, they will become less useful as code until we clean out the attic, which may be years from now.&lt;/p&gt;
&lt;h2&gt;Package Updates&lt;/h2&gt;
&lt;p&gt;In addition, we've done a round of updates to keep everything running smoothly and handle some vulerability warnings in our dependencies. Overall, this was a simply process except libraries dealing with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CLI&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MfGames.Nitride.IO&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For the CLI, we use &lt;a href="https://github.com/dotnet/command-line-api"&gt;System.CommandLine&lt;/a&gt; as the base of our &lt;code&gt;MfGames.ToolBuilder&lt;/code&gt; library, which is basically an opionated setup that uses &lt;code&gt;Serilog&lt;/code&gt;, &lt;code&gt;Autofac&lt;/code&gt;, and dependecy-injected commands. When moving from version &lt;code&gt;2.0.0-beta8&lt;/code&gt; (it was in beta for over five years) to &lt;code&gt;2.0.9&lt;/code&gt;, there were some drastic refactoring that needed to be done. This resulted in all the CLI commands (&lt;code&gt;MfGames.ToolBuilder&lt;/code&gt; and &lt;code&gt;MfGames.Nitride&lt;/code&gt;) having a breaking change since the signatures changed across the board. There were relatively few dependencies on this, but they were all bumped to major versions.&lt;/p&gt;
&lt;p&gt;For the other libraries, this was a feature (0.x.0) update because of potential side effects we haven't been able to identify.&lt;/p&gt;
&lt;h3&gt;MfGames.Nitride.IO&lt;/h3&gt;
&lt;p&gt;The other change was &lt;code&gt;MfGames.Nitride.IO&lt;/code&gt;. In specific, we changed how the &lt;code&gt;ReadFiles&lt;/code&gt; operation worked because of real-world difficulties. Most of our IO operations are based on the excellent library, &lt;a href="https://github.com/xoofx/zio"&gt;Zio&lt;/a&gt; which gives use &lt;code&gt;UPath&lt;/code&gt; which simplifies path processing, virtual file systems which makes test writing a lot easier, and remapped structures that let us treat a folder as &lt;code&gt;/sources/allegro&lt;/code&gt; as &lt;code&gt;/&lt;/code&gt; so our &lt;a href="//fedran.com"&gt;Fedran&lt;/a&gt; can treat each project Git repository as a root folder, which simplifies logic. We also like using &lt;a href="https://github.com/kthompson/glob/"&gt;recursive globbing&lt;/a&gt; (ones that use &lt;code&gt;**&lt;/code&gt; to recurse into dirctories in addition to &lt;code&gt;*&lt;/code&gt; for matching at a given level).&lt;/p&gt;
&lt;p&gt;The problem is that Zio doesn't support globbing natively. So our original implementation was to iterate through every file using Zio, then compare it against the glob.&lt;/p&gt;
&lt;p&gt;For simple cases, this was fast. However, when we're doing a search like &lt;code&gt;/src/**/chapter-*.md&lt;/code&gt; in a project directory, this also processed through &lt;code&gt;/node_modules&lt;/code&gt;, &lt;code&gt;.direnv/&lt;/code&gt;, and &lt;code&gt;target/&lt;/code&gt; folders which have a staggering amount of files that we don't want.&lt;/p&gt;
&lt;p&gt;Nowe, we have both include and exclude patterns in an ordered list. For each one, we parse the pattern and attempt to do some simple heuristics with the root comparisons before we devolve into the &amp;ldquo;grab everything to compare it&amp;rdquo;. What this means that for &lt;code&gt;/src/**/chapter-*.md&lt;/code&gt;, we go into &lt;code&gt;/src&lt;/code&gt; before we grab everything. The other massive folders are looked at, and the code chooses not to go into it. If there are no &lt;code&gt;**&lt;/code&gt; in the pattern, this will give us a rather prescise scan which is faster than before.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;// Old version
ReadFiles readFiles = Resolve&amp;lt;ReadFiles&amp;gt;()
  .WithPattern(&amp;quot;/chapters/chapter-*.md&amp;quot;);

// Old version without using the .With* methods.
ReadFiles readFiles2 = Resolve&amp;lt;ReadFiles&amp;gt;();
readFiles2.Pattern = &amp;quot;/chapters/chapter-*.md&amp;quot;;

// New Version
ReadFiles readFiles = Resolve&amp;lt;ReadFiles&amp;gt;()
    .AddIncludePattern(&amp;quot;/chapters/chapter-*.md&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To keep the conventions from &lt;code&gt;.gitignore&lt;/code&gt; and other files, if you give the pattern as &lt;code&gt;*.txt&lt;/code&gt;, we change it to &lt;code&gt;/**/*.txt&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Which leads to the exclude patterns. &lt;code&gt;/**&lt;/code&gt; effectively goes back to the old code of grabbing everything and comparing it. But if you then add an exclude pattern (ideally without a &lt;code&gt;**&lt;/code&gt;), it will stop processing the includes if it already knows it will be excluding it.&lt;/p&gt;
&lt;pre&gt;&lt;code class="language-csharp"&gt;ReadFiles readFiles = Resolve&amp;lt;ReadFiles&amp;gt;()
    .AddIncludePattern(&amp;quot;/**/chapters/chapter-*.md&amp;quot;)
    .AddExcludePattern(&amp;quot;/node_modules&amp;quot;)
    .AddExcludePatternList(
        &amp;quot;/.direnv&amp;quot;,
        &amp;quot;/target&amp;quot;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This will eventually lead up to being able to pass in &lt;code&gt;.gitignore&lt;/code&gt; directly into the code, but we want the code base to settle (e.g., use it for awhile) before we add that.&lt;/p&gt;
&lt;p&gt;There is also a &lt;code&gt;.WithPatternList()&lt;/code&gt; which takes a list of a typesafe collection, but that's a more edge case and if you need that, then you might want to look at our tests for examples of how to write those.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Online Documentation (MfGames .NET Libraries)</title>
    <link rel="alternate" href="https://mfgames.com/blog/2024/04/20/online-documentation/" />
    <updated>2024-04-20T05:00:00Z</updated>
    <id>https://mfgames.com/blog/2024/04/20/online-documentation/</id>
    <category term="mfgames-net-libraries" scheme="https://mfgames.com/categories/" label="MfGames .NET Libraries" />
    <content type="html">&lt;p&gt;When we started Nitride in May 2021, we always intended to convert all our websites to use the new system. Admitedly, we started with the most complex sites because that would iron out the more complex problems we were trying to solve with Nitride. And there were some rather significant patterns to iron out over the years.&lt;/p&gt;
&lt;p&gt;But &lt;a href="/"&gt;mfgames.com&lt;/a&gt; was one of those lynchpins for the entire migration because if a program or library isn't documented, it can't be ever be done. And we had examples and patterns, but no good place to point someone who might be interested in using Nitride with something narrative instead of &amp;ldquo;look at the tests&amp;rdquo; or &amp;ldquo;look at these examples.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Now we have it. Adding documentation to our &lt;code&gt;./docs/&lt;/code&gt; folder will automatically show up on the &lt;a href="//mfgames.com/mfgames-cil/"&gt;website&lt;/a&gt;. That will also open up the ability to write tutorials on how to use the library, news of what is going on that can be subscribed with feed readers (and maybe a mailing list), and generally those little polish things needed to call something &amp;ldquo;done.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Here is to the next big step.&lt;/p&gt;
</content>
  </entry>
</feed>
