<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xml:base="https://oatmeal.gg/" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Oatmeal Problem</title>
    <link>https://oatmeal.gg/</link>
    <atom:link href="https://oatmeal.gg/rss.xml" rel="self" type="application/rss+xml" />
    <description>A blog where I post about game dev, web tech, or whatever else I&#39;m up to.</description>
    <language>en</language>
    <item>
      <title>Scoop of Oatmeal, May &#39;26</title>
      <link>https://oatmeal.gg/blog/scoop-2026-05/</link>
      <description>&lt;h2&gt;Paint a Galaxy&lt;/h2&gt;
&lt;p&gt;The rewrite/redesign released in March promised greater productivity from a code technical perspective, and a UI that could more easily adapt to additional features. Good news, it worked! I&#39;ve been able to release many large and small features the past 2 months:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;choose placement of unique systems (by setting &lt;code&gt;initializier&lt;/code&gt;s)&lt;/li&gt;
&lt;li&gt;set custom solar system names&lt;/li&gt;
&lt;li&gt;configurable snap-to-grid with various grid types (square, triangle, hex, radial)&lt;/li&gt;
&lt;li&gt;new drawing tools (ellipse, rectangle, line)&lt;/li&gt;
&lt;li&gt;export and import projects&lt;/li&gt;
&lt;li&gt;clone projects&lt;/li&gt;
&lt;li&gt;pan the map with arrows/WASD&lt;/li&gt;
&lt;li&gt;step-specific canvas opacity settings (so you can optionally reference your painting or uploaded image in the Tweak step)&lt;/li&gt;
&lt;li&gt;in-app guides for Gigastructural Engineering core&lt;/li&gt;
&lt;li&gt;various fixes to both the app and the mod&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Paint a Galaxy is still my focus. In the coming weeks, I plan to work on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;custom fallen empire spawn areas&lt;/li&gt;
&lt;li&gt;move systems with a drag &amp;#x26; drop tool&lt;/li&gt;
&lt;li&gt;symmetry tools&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then I&#39;ll run another poll in Discord to help drive priorities.&lt;/p&gt;</description>
      <pubDate>Sun, 03 May 2026 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/scoop-2026-05/</guid>
    </item>
    <item>
      <title>Scoop of Oatmeal, March &#39;26</title>
      <link>https://oatmeal.gg/blog/scoop-2026-03/</link>
      <description>&lt;p&gt;Progress has been sporadic the past few months, but finally getting back into the groove.&lt;/p&gt;
&lt;h2&gt;Paint a Galaxy&lt;/h2&gt;
&lt;p&gt;The big Paint a Galaxy redesign has been released! This was almost a complete re-write of the web app. The highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Save/load multiple projects, so you don&#39;t need to lose a map to start a new one&lt;/li&gt;
&lt;li&gt;Undo/redo now works for all edit actions, not just painting&lt;/li&gt;
&lt;li&gt;Pan and zoom the map&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This also lays the UI and technical foundation for many other requested features. My plan back in December had been to work on Paint a Galaxy for the next month-ish, then go back to StellarMaps. We&#39;re well past that, and this project still has my attention. New plan: work on it until I lose interest. I&#39;d like to implement at least the following, with some minor features and usability improvements mixed in:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Custom names for systems&lt;/li&gt;
&lt;li&gt;Choose where specific players and pre-designed AI empires spawn&lt;/li&gt;
&lt;li&gt;Choose where unique systems spawn&lt;/li&gt;
&lt;li&gt;Configurable grid with snap-to-grid functionality for painting, generating, and tweaking
&lt;ul&gt;
&lt;li&gt;Multiple grid types: square, hex, triangle, radial&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Configurable symmetry tools (both bilateral and radial) for painting, generating, and tweaking&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Thu, 05 Mar 2026 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/scoop-2026-03/</guid>
    </item>
    <item>
      <title>Scoop of Oatmeal, December &#39;25</title>
      <link>https://oatmeal.gg/blog/scoop-2025-12/</link>
      <description>&lt;h2&gt;Paint a galaxy&lt;/h2&gt;
&lt;p&gt;This month, I contributed &lt;a href=&quot;https://www.skeleton.dev/docs/svelte/framework-components/steps&quot;&gt;a Steps component for Skeleton&lt;/a&gt; (a UI component library). At a glance, that&#39;s not anything to do with Paint a Galaxy. In fact, Paint a Galaxy doesn&#39;t even use Skeleton, it uses the more minimalist &lt;a href=&quot;https://picocss.com&quot;&gt;Pico CSS&lt;/a&gt; instead. However, it&#39;s starting outgrow Pico CSS&#39;s limited feature set. This next month, I&#39;ll be converting it over to Skeleton and redesigning the UI to better accomodate more painting tools and customization features (and using that &quot;steps&quot; component among others).&lt;/p&gt;
&lt;p&gt;Well, how about those features I&#39;ll be implementing? In no particular order:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;zooming and panning the paint canvas&lt;/li&gt;
&lt;li&gt;symmetry, circle, and spiral tools&lt;/li&gt;
&lt;li&gt;guides (eg core, L-cluster)&lt;/li&gt;
&lt;li&gt;projects (save and work on multiple maps)&lt;/li&gt;
&lt;li&gt;customize unique system locations&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After that, I expect Paint a Galaxy to go mostly dormant as I return focus to StellarMaps.&lt;/p&gt;
&lt;h1&gt;Stellaris Mods&lt;/h1&gt;
&lt;p&gt;Stellaris released v4.2, and with a Stellaris update comes mod updates. I try my best to design my mods to be low-maintenance and that worked out well this time, with all except one requiring no changes (and the the one needing only minor changes).&lt;/p&gt;</description>
      <pubDate>Thu, 04 Dec 2025 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/scoop-2025-12/</guid>
    </item>
    <item>
      <title>Scoop of Oatmeal, November &#39;25</title>
      <link>https://oatmeal.gg/blog/scoop-2025-11/</link>
      <description>&lt;p&gt;I&#39;m overdue for an update here! Life has been busy with events both expected and unexpected, but I&#39;ve managed some progress since August&#39;s post.&lt;/p&gt;
&lt;h2&gt;Paint a galaxy&lt;/h2&gt;
&lt;p&gt;Paint a Galaxy now lets you place custom wormholes. You can use it to create map with regions connected only by wormhole. Combined with spawn customization, you could make a star clusters that aren&#39;t unexplorable early game, so there&#39;s a mid-game colonization rush. Other than that, I fixed lots of bugs. It&#39;s a bit boring, but I did manage to fix every known fixable issue!&lt;/p&gt;
&lt;p&gt;This will continue to be my main project for the short-term. Now that the mod part is in a good place, I&#39;m going to improve the UI and editing tools, while also exploring some technology I&#39;ll potentially incorporate into StellarMaps.&lt;/p&gt;
&lt;h1&gt;Other Development&lt;/h1&gt;
&lt;p&gt;Since Augist, I&#39;ve made a few small updates to this site. I also contributed a fix for &lt;a href=&quot;https://shiki.style/packages/colorized-brackets&quot;&gt;Shiki&#39;s Colorized Brackets plugin&lt;/a&gt;. I wrote that plugin, so I try to keep an eye out for issues to help maintain it.&lt;/p&gt;
&lt;h2&gt;Support Me&lt;/h2&gt;
&lt;p&gt;A few folks have asked in the past, so I&#39;ve finally set up some methods to support me monetarily:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/sponsors/oatmealproblem&quot;&gt;GitHub Sponsorships&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://patreon.com/oatmealproblem&quot;&gt;Patreon&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://buymeacoffee.com/oatmealproblem&quot;&gt;Buy Me a Coffee&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Things are pretty bare-bones there, so I&#39;ll work on filling out those pages some more.&lt;/p&gt;
&lt;p&gt;Don&#39;t worry, all my work will remain free and open source. I have no short-term plans to attach any rewards to donations (though I might later add Discord roles, credits, etc). For now, you will just receive my heart-felt gratitude ❤️&lt;/p&gt;</description>
      <pubDate>Tue, 04 Nov 2025 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/scoop-2025-11/</guid>
    </item>
    <item>
      <title>Scoop of Oatmeal, August &#39;25</title>
      <link>https://oatmeal.gg/blog/scoop-2025-08/</link>
      <description>&lt;h2&gt;StellarMaps&lt;/h2&gt;
&lt;p&gt;This past month, I continued working on converting features to the new Stellaris-independent data format. Wormholes, gateways, terra incognita, and relations mode are all working again. The largest remaining work there is solar system maps. Besides that, I need to convert a few more map modes, and implement some minor features like player names. All this data processing work is a bit boring to work on, but will be good in the long term. I also got fixes out for bugs that have been reported over the past few weeks.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/scoop-2025-08/Un2k286uPn-800.webp&quot; alt=&quot;Stellaris map in relations mode&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;800&quot; height=&quot;600&quot;&gt;&lt;/p&gt;
&lt;p&gt;To keep my interest, I decided to experiment with controls for creating a galaxy from scratch. This won&#39;t be in the next version, perhaps not even the version after that, but I wanted to work through some of the UX difficulties (and it sounded fun). Most simply, you could create a galaxy by hand placing each star and connection between stars. That would be quite tedious though for anything beyond a few stars, so some sort of random generation is needed. To strike a balance between automatic generation and user input, I experimented with &quot;painting&quot; the areas you want stars, then randomly placing stars based on how &quot;bright&quot; you painted each area. I also implemented an algorithm to place hyperlanes between the stars, with inputs for connectedness and maximum length, while guaranteeing that no hyperlanes cross and everything is connected.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/scoop-2025-08/PXi6WJElt_-900.webp&quot; alt=&quot;Painted map of 2 colliding galaxies&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;900&quot; height=&quot;900&quot;&gt;&lt;/p&gt;
&lt;p&gt;Success! I had a lot of fun just drawing different shapes. It felt like a shame it would be so long before it was usable... but I wondered, how much work would it be to output a Stellaris static galaxy mod?&lt;/p&gt;
&lt;h2&gt;Paint a Galaxy&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/scoop-2025-08/6exZmLXkHd-920.webp&quot; alt=&quot;Thumbnail of Paint a Galaxy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;920&quot;&gt;&lt;/p&gt;
&lt;p&gt;I spun &quot;Paint a Galaxy&quot; out into it&#39;s own project, as a combo of &lt;a href=&quot;https://oatmealproblem.github.io/paint-a-galaxy&quot;&gt;web app to create a custom galaxy&lt;/a&gt; and &lt;a href=&quot;https://steamcommunity.com/workshop/filedetails/?id=3532904115&quot;&gt;mod to play it in Stellaris&lt;/a&gt;! This was at first easier than expected, but then became quite a bit of work as I discovered the various ways static galaxy mods don&#39;t quite behave like you&#39;d expect. I fixed the worst of the issues, then released to a better than expected reception -- for a bit, the project was the top trending post in r/stellaris and the Stellaris Steam Workshop!&lt;/p&gt;
&lt;p&gt;I expect Paint a Galaxy to remain my focus the next month or so, but I&#39;m intentionally keeping the focus pretty tight. There are many niche use-cases I &lt;em&gt;could&lt;/em&gt; support, but I don&#39;t want to bloat the app, so I&#39;ll instead direct folks to manually mod their custom galaxies (and perhaps write some guides for some of the more common requests).&lt;/p&gt;
&lt;h1&gt;Other Stuff&lt;/h1&gt;
&lt;p&gt;Where else have I been up to?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;As always work and house work&lt;/li&gt;
&lt;li&gt;I&#39;m continuing my studies of Japanese and Chinese
&lt;ul&gt;
&lt;li&gt;I&#39;m looking for a Chinese language practice partner -- reach out if you&#39;re interested!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I started working through &lt;a href=&quot;https://hands-on-rust.com/&quot;&gt;Hands-On Rust&lt;/a&gt; to fill some knowledge gaps&lt;/li&gt;
&lt;li&gt;This month I&#39;ve continued playing Morrowind and returned to Against the Stone -- both are amazing&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Sat, 09 Aug 2025 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/scoop-2025-08/</guid>
    </item>
    <item>
      <title>Scoop of Oatmeal, July &#39;25</title>
      <link>https://oatmeal.gg/blog/scoop-2025-07/</link>
      <description>&lt;h2&gt;StellarMaps&lt;/h2&gt;
&lt;p&gt;It&#39;s been a relatively slow month for StellarMaps. I continue to make progress on the Stellaris-independent data format. Most notably, &lt;em&gt;unions mode&lt;/em&gt; (federations and subjects) is now working. In the new data format, unions are represented as factions that have other factions as members, which can be deeply nested. Although data imported from Stellaris won&#39;t make use of that, in the future when map editing is supported, it could be used for complex feudal structures.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/scoop-2025-07/ea7GVQZg97-920.webp&quot; alt=&quot;Stellaris map in unions mode&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;920&quot;&gt;&lt;/p&gt;
&lt;p&gt;Even more behind-the-scenes, I&#39;ve pulled in the library &lt;a href=&quot;https://effect.website&quot;&gt;Effect&lt;/a&gt; to help with data processing. This provides robust type checking and error handling. Currently, I&#39;m mostly using it to define the &lt;code&gt;Snapshot&lt;/code&gt; data structures with validators and helper methods. For example, here&#39;s the &lt;code&gt;Faction&lt;/code&gt; class:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;style&gt;.expressive-code{font-family:var(--ec-uiFontFml);font-size:var(--ec-uiFontSize);font-weight:var(--ec-uiFontWg);line-height:var(--ec-uiLineHt);text-size-adjust:none;-webkit-text-size-adjust:none}.expressive-code *:not(:is(svg, svg *)){all:revert;box-sizing:border-box}.expressive-code pre{display:flex;margin:0;padding:0;border:var(--ec-brdWd) solid var(--ec-brdCol);border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));background:var(--ec-codeBg)}.expressive-code pre:focus-visible{outline:3px solid var(--ec-focusBrd);outline-offset:-3px}.expressive-code pre &gt; code{all:unset;display:block;flex:1 0 100%;padding:var(--ec-codePadBlk) 0;color:var(--ec-codeFg);font-family:var(--ec-codeFontFml);font-size:var(--ec-codeFontSize);font-weight:var(--ec-codeFontWg);line-height:var(--ec-codeLineHt)}.expressive-code pre{overflow-x:auto}.expressive-code pre.wrap .ec-line .code{white-space:pre-wrap;overflow-wrap:break-word;min-width:min(20ch, var(--ecMaxLine, 20ch))}.expressive-code pre.wrap .ec-line .code span.indent{white-space:pre}.expressive-code pre::-webkit-scrollbar,.expressive-code pre::-webkit-scrollbar-track{background-color:inherit;border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));border-top-left-radius:0;border-top-right-radius:0}.expressive-code pre::-webkit-scrollbar-thumb{background-color:var(--ec-sbThumbCol);border:4px solid transparent;background-clip:content-box;border-radius:10px}.expressive-code pre::-webkit-scrollbar-thumb:hover{background-color:var(--ec-sbThumbHoverCol)}.expressive-code .ec-line{direction:ltr;unicode-bidi:isolate;display:grid;grid-template-areas:&#39;gutter code&#39;;grid-template-columns:auto 1fr;position:relative}.expressive-code .ec-line .gutter{grid-area:gutter;color:var(--ec-gtrFg)}.expressive-code .ec-line .gutter &gt; *{pointer-events:none;user-select:none;-webkit-user-select:none}.expressive-code .ec-line .gutter ~ .code{--ecLineBrdCol:var(--ec-gtrBrdCol)}.expressive-code .ec-line.highlight .gutter{color:var(--ec-gtrHlFg)}.expressive-code .ec-line .code{grid-area:code;position:relative;box-sizing:content-box;padding-inline-start:calc(var(--ecIndent, 0ch) + var(--ec-codePadInl) - var(--ecGtrBrdWd));padding-inline-end:var(--ec-codePadInl);text-indent:calc(var(--ecIndent, 0ch) * -1)}.expressive-code .ec-line .code::before,.expressive-code .ec-line .code::after,.expressive-code .ec-line .code :where(*){text-indent:0}.expressive-code .ec-line .code{--ecGtrBrdWd:var(--ec-gtrBrdWd);border-inline-start:var(--ecGtrBrdWd) solid var(--ecLineBrdCol, transparent)}.expressive-code .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0}.expressive-code .ec-line.mark{--tmLineBgCol:var(--ec-tm-markBg)}.expressive-code .ec-line.mark .code{--ecLineBrdCol:var(--ec-tm-markBrdCol)}.expressive-code .ec-line.ins{--tmLineBgCol:var(--ec-tm-insBg);--tmLabel:var(--ec-tm-insDiffIndContent)}.expressive-code .ec-line.ins .code{--ecLineBrdCol:var(--ec-tm-insBrdCol)}.expressive-code .ec-line.ins .code::before{color:var(--ec-tm-insDiffIndCol)}.expressive-code .ec-line.del{--tmLineBgCol:var(--ec-tm-delBg);--tmLabel:var(--ec-tm-delDiffIndContent)}.expressive-code .ec-line.del .code{--ecLineBrdCol:var(--ec-tm-delBrdCol)}.expressive-code .ec-line.del .code::before{color:var(--ec-tm-delDiffIndCol)}.expressive-code .ec-line.mark,.expressive-code .ec-line.ins,.expressive-code .ec-line.del{background:var(--tmLineBgCol)}.expressive-code .ec-line.mark .code,.expressive-code .ec-line.ins .code,.expressive-code .ec-line.del .code{--ecGtrBrdWd:var(--ec-tm-lineMarkerAccentWd)}.expressive-code .ec-line.mark .code::before,.expressive-code .ec-line.ins .code::before,.expressive-code .ec-line.del .code::before{display:block;position:absolute;left:0;box-sizing:border-box;content:var(--tmLabel, &#39; &#39;);padding-inline-start:var(--ec-tm-lineDiffIndMargLeft);text-align:center;white-space:pre}.expressive-code .ec-line.mark.tm-label .code::before,.expressive-code .ec-line.ins.tm-label .code::before,.expressive-code .ec-line.del.tm-label .code::before{background:var(--ecLineBrdCol);padding:0 calc(var(--ec-tm-lineMarkerLabelPadInl) + var(--ec-tm-lineMarkerAccentWd)) 0 var(--ec-tm-lineMarkerLabelPadInl);color:var(--ec-tm-lineMarkerLabelCol)}.expressive-code .ec-line mark{--tmInlineBgCol:var(--ec-tm-markBg);--tmInlineBrdCol:var(--ec-tm-markBrdCol)}.expressive-code .ec-line ins{--tmInlineBgCol:var(--ec-tm-insBg);--tmInlineBrdCol:var(--ec-tm-insBrdCol)}.expressive-code .ec-line del{--tmInlineBgCol:var(--ec-tm-delBg);--tmInlineBrdCol:var(--ec-tm-delBrdCol)}.expressive-code .ec-line mark,.expressive-code .ec-line ins,.expressive-code .ec-line del{all:unset;display:inline-block;position:relative;--tmBrdL:var(--ec-tm-inlMarkerBrdWd);--tmBrdR:var(--ec-tm-inlMarkerBrdWd);--tmRadL:var(--ec-tm-inlMarkerBrdRad);--tmRadR:var(--ec-tm-inlMarkerBrdRad);margin-inline:0.025rem;padding-inline:var(--ec-tm-inlMarkerPad);border-radius:var(--tmRadL) var(--tmRadR) var(--tmRadR) var(--tmRadL);background:var(--tmInlineBgCol);background-clip:padding-box}.expressive-code .ec-line mark.open-start,.expressive-code .ec-line ins.open-start,.expressive-code .ec-line del.open-start{margin-inline-start:0;padding-inline-start:0;--tmBrdL:0px;--tmRadL:0}.expressive-code .ec-line mark.open-end,.expressive-code .ec-line ins.open-end,.expressive-code .ec-line del.open-end{margin-inline-end:0;padding-inline-end:0;--tmBrdR:0px;--tmRadR:0}.expressive-code .ec-line mark::before,.expressive-code .ec-line ins::before,.expressive-code .ec-line del::before{content:&#39;&#39;;position:absolute;pointer-events:none;display:inline-block;inset:0;border-radius:var(--tmRadL) var(--tmRadR) var(--tmRadR) var(--tmRadL);border:var(--ec-tm-inlMarkerBrdWd) solid var(--tmInlineBrdCol);border-inline-width:var(--tmBrdL) var(--tmBrdR)}.expressive-code .frame{all:unset;position:relative;display:block;--header-border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));--tab-border-radius:calc(var(--ec-frm-edTabBrdRad) + var(--ec-brdWd));--button-spacing:0.4rem;--code-background:var(--ec-frm-edBg);border-radius:var(--header-border-radius);box-shadow:var(--ec-frm-frameBoxShdCssVal)}.expressive-code .frame .header{display:none;z-index:1;position:relative;border-radius:var(--header-border-radius) var(--header-border-radius) 0 0}.expressive-code .frame.has-title pre,.expressive-code .frame.has-title code,.expressive-code .frame.is-terminal pre,.expressive-code .frame.is-terminal code{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.expressive-code .frame .title:empty:before{content:&#39;&#92;a0&#39;}.expressive-code .frame.has-title:not(.is-terminal){--button-spacing:calc(1.9rem + 2 * (var(--ec-uiPadBlk) + var(--ec-frm-edActTabIndHt)))}.expressive-code .frame.has-title:not(.is-terminal) .title{position:relative;color:var(--ec-frm-edActTabFg);background:var(--ec-frm-edActTabBg);background-clip:padding-box;margin-block-start:var(--ec-frm-edTabsMargBlkStart);padding:calc(var(--ec-uiPadBlk) + var(--ec-frm-edActTabIndHt)) var(--ec-uiPadInl);border:var(--ec-brdWd) solid var(--ec-frm-edActTabBrdCol);border-radius:var(--tab-border-radius) var(--tab-border-radius) 0 0;border-bottom:none;overflow:hidden}.expressive-code .frame.has-title:not(.is-terminal) .title::after{content:&#39;&#39;;position:absolute;pointer-events:none;inset:0;border-top:var(--ec-frm-edActTabIndHt) solid var(--ec-frm-edActTabIndTopCol);border-bottom:var(--ec-frm-edActTabIndHt) solid var(--ec-frm-edActTabIndBtmCol)}.expressive-code .frame.has-title:not(.is-terminal) .header{display:flex;background:linear-gradient(to top, var(--ec-frm-edTabBarBrdBtmCol) var(--ec-brdWd), transparent var(--ec-brdWd)),linear-gradient(var(--ec-frm-edTabBarBg), var(--ec-frm-edTabBarBg));background-repeat:no-repeat;padding-inline-start:var(--ec-frm-edTabsMargInlStart)}.expressive-code .frame.has-title:not(.is-terminal) .header::before{content:&#39;&#39;;position:absolute;pointer-events:none;inset:0;border:var(--ec-brdWd) solid var(--ec-frm-edTabBarBrdCol);border-radius:inherit;border-bottom:none}.expressive-code .frame.is-terminal{--button-spacing:calc(1.9rem + var(--ec-brdWd) + 2 * var(--ec-uiPadBlk));--code-background:var(--ec-frm-trmBg)}.expressive-code .frame.is-terminal .header{display:flex;align-items:center;justify-content:center;padding-block:var(--ec-uiPadBlk);padding-block-end:calc(var(--ec-uiPadBlk) + var(--ec-brdWd));position:relative;font-weight:500;letter-spacing:0.025ch;color:var(--ec-frm-trmTtbFg);background:var(--ec-frm-trmTtbBg);border:var(--ec-brdWd) solid var(--ec-brdCol);border-bottom:none}.expressive-code .frame.is-terminal .header::before{content:&#39;&#39;;position:absolute;pointer-events:none;left:var(--ec-uiPadInl);width:2.1rem;height:0.56rem;line-height:0;background-color:var(--ec-frm-trmTtbDotsFg);opacity:var(--ec-frm-trmTtbDotsOpa);-webkit-mask-image:var(--ec-frm-trmIcon);-webkit-mask-repeat:no-repeat;mask-image:var(--ec-frm-trmIcon);mask-repeat:no-repeat}.expressive-code .frame.is-terminal .header::after{content:&#39;&#39;;position:absolute;pointer-events:none;inset:0;border-bottom:var(--ec-brdWd) solid var(--ec-frm-trmTtbBrdBtmCol)}.expressive-code .frame pre{background:var(--code-background)}.expressive-code .copy{display:flex;gap:0.25rem;flex-direction:row;position:absolute;inset-block-start:calc(var(--ec-brdWd) + var(--button-spacing));inset-inline-end:calc(var(--ec-brdWd) + var(--ec-uiPadInl) / 2)}@media (scripting: none){.expressive-code .copy{display:none}}.expressive-code .copy{direction:ltr;unicode-bidi:isolate}.expressive-code .copy button{position:relative;align-self:flex-end;margin:0;padding:0;border:none;border-radius:0.2rem;z-index:1;cursor:pointer;transition-property:opacity, background, border-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.25, 0.46, 0.45, 0.94);width:2.5rem;height:2.5rem;background:var(--code-background);opacity:0.75}.expressive-code .copy button div{position:absolute;inset:0;border-radius:inherit;background:var(--ec-frm-inlBtnBg);opacity:var(--ec-frm-inlBtnBgIdleOpa);transition-property:inherit;transition-duration:inherit;transition-timing-function:inherit}.expressive-code .copy button::before{content:&#39;&#39;;position:absolute;pointer-events:none;inset:0;border-radius:inherit;border:var(--ec-brdWd) solid var(--ec-frm-inlBtnBrd);opacity:var(--ec-frm-inlBtnBrdOpa)}.expressive-code .copy button::after{content:&#39;&#39;;position:absolute;pointer-events:none;inset:0;background-color:var(--ec-frm-inlBtnFg);-webkit-mask-image:var(--ec-frm-copyIcon);-webkit-mask-repeat:no-repeat;mask-image:var(--ec-frm-copyIcon);mask-repeat:no-repeat;margin:0.475rem;line-height:0}.expressive-code .copy button:hover,.expressive-code .copy button:focus:focus-visible{opacity:1}.expressive-code .copy button:hover div,.expressive-code .copy button:focus:focus-visible div{opacity:var(--ec-frm-inlBtnBgHoverOrFocusOpa)}.expressive-code .copy button:active{opacity:1}.expressive-code .copy button:active div{opacity:var(--ec-frm-inlBtnBgActOpa)}.expressive-code .copy .feedback{--tooltip-arrow-size:0.35rem;--tooltip-bg:var(--ec-frm-tooltipSuccessBg);color:var(--ec-frm-tooltipSuccessFg);pointer-events:none;user-select:none;-webkit-user-select:none;position:relative;align-self:center;background-color:var(--tooltip-bg);z-index:99;padding:0.125rem 0.75rem;border-radius:0.2rem;margin-inline-end:var(--tooltip-arrow-size);opacity:0;transition-property:opacity, transform;transition-duration:0.2s;transition-timing-function:ease-in-out;transform:translate3d(0, 0.25rem, 0)}.expressive-code .copy .feedback::after{content:&#39;&#39;;position:absolute;pointer-events:none;top:calc(50% - var(--tooltip-arrow-size));inset-inline-end:calc(-2 * (var(--tooltip-arrow-size) - 0.5px));border:var(--tooltip-arrow-size) solid transparent;border-inline-start-color:var(--tooltip-bg)}.expressive-code .copy .feedback.show{opacity:1;transform:translate3d(0, 0, 0)}@media (hover: hover){.expressive-code{}.expressive-code .copy button{opacity:0;width:2rem;height:2rem}.expressive-code .frame:hover .copy button:not(:hover),.expressive-code .frame:focus-within :focus-visible ~ .copy button:not(:hover),.expressive-code .frame .copy .feedback.show ~ button:not(:hover){opacity:0.75}}.expressive-code :nth-child(1 of .ec-line) .code{padding-inline-end:calc(2rem + var(--ec-codePadInl))}:root,:root:not([data-theme=&#39;dark-plus&#39;]) .expressive-code[data-theme=&#39;dark-plus&#39;]{--ec-brdRad:0.3rem;--ec-brdWd:1.5px;--ec-brdCol:var(--pico-blockquote-border-color);--ec-codeFontFml:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,&#39;Liberation Mono&#39;,&#39;Courier New&#39;,monospace;--ec-codeFontSize:0.85rem;--ec-codeFontWg:400;--ec-codeLineHt:1.65;--ec-codePadBlk:1rem;--ec-codePadInl:1.35rem;--ec-codeBg:var(--pico-code-background-color);--ec-codeFg:#d4d4d4;--ec-codeSelBg:#264f78;--ec-gtrFg:#858585;--ec-gtrBrdCol:#85858533;--ec-gtrBrdWd:1.5px;--ec-gtrHlFg:#c6c6c6;--ec-uiFontFml:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Roboto,&#39;Helvetica Neue&#39;,Arial,&#39;Noto Sans&#39;,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;,&#39;Noto Color Emoji&#39;;--ec-uiFontSize:0.9rem;--ec-uiFontWg:400;--ec-uiLineHt:1.65;--ec-uiPadBlk:0.25rem;--ec-uiPadInl:1rem;--ec-uiSelBg:#0078d4;--ec-uiSelFg:#ffffff;--ec-focusBrd:#007fd4;--ec-sbThumbCol:#79797966;--ec-sbThumbHoverCol:#646464b2;--ec-tm-lineMarkerAccentMarg:0rem;--ec-tm-lineMarkerAccentWd:0.15rem;--ec-tm-lineMarkerLabelPadInl:0.2rem;--ec-tm-lineMarkerLabelCol:white;--ec-tm-lineDiffIndMargLeft:0.3rem;--ec-tm-inlMarkerBrdWd:1.5px;--ec-tm-inlMarkerBrdRad:0.2rem;--ec-tm-inlMarkerPad:0.15rem;--ec-tm-insDiffIndContent:&#39;+&#39;;--ec-tm-delDiffIndContent:&#39;-&#39;;--ec-tm-markBg:#264a8980;--ec-tm-markBrdCol:#5570b3d0;--ec-tm-insBg:#26561c80;--ec-tm-insBrdCol:#4e7e41d0;--ec-tm-insDiffIndCol:#7eb070d0;--ec-tm-delBg:#81322b80;--ec-tm-delBrdCol:#ae594fd0;--ec-tm-delDiffIndCol:#e68a7ed0;--ec-frm-shdCol:#0000005b;--ec-frm-frameBoxShdCssVal:0.1rem 0.1rem 0.2rem #0000005b;--ec-frm-edActTabBg:var(--pico-code-background-color);--ec-frm-edActTabFg:#ffffff;--ec-frm-edActTabBrdCol:transparent;--ec-frm-edActTabIndHt:1.5px;--ec-frm-edActTabIndTopCol:null;--ec-frm-edActTabIndBtmCol:null;--ec-frm-edTabsMargInlStart:0;--ec-frm-edTabsMargBlkStart:0;--ec-frm-edTabBrdRad:0.3rem;--ec-frm-edTabBarBg:var(--pico-background-color);--ec-frm-edTabBarBrdCol:var(--pico-blockquote-border-color);--ec-frm-edTabBarBrdBtmCol:transparent;--ec-frm-edBg:var(--pico-code-background-color);--ec-frm-trmTtbFg:#cccccc;--ec-frm-trmTtbDotsFg:#cccccc;--ec-frm-trmTtbDotsOpa:0.15;--ec-frm-trmTtbBg:var(--pico-background-color);--ec-frm-trmTtbBrdBtmCol:#000000bf;--ec-frm-trmBg:var(--pico-code-background-color);--ec-frm-inlBtnFg:#d4d4d4;--ec-frm-inlBtnBg:#d4d4d4;--ec-frm-inlBtnBgIdleOpa:0;--ec-frm-inlBtnBgHoverOrFocusOpa:0.2;--ec-frm-inlBtnBgActOpa:0.3;--ec-frm-inlBtnBrd:#d4d4d4;--ec-frm-inlBtnBrdOpa:0.4;--ec-frm-tooltipSuccessBg:#098656;--ec-frm-tooltipSuccessFg:white;--ec-frm-copyIcon:url(&quot;data:image/svg+xml,%3Csvg%20xmlns%3D&#39;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&#39;%20viewBox%3D&#39;0%200%2024%2024&#39;%20fill%3D&#39;none&#39;%20stroke%3D&#39;black&#39;%20stroke-width%3D&#39;1.75&#39;%3E%3Cpath%20d%3D&#39;M3%2019a2%202%200%200%201-1-2V2a2%202%200%200%201%201-1h13a2%202%200%200%201%202%201&#39;%2F%3E%3Crect%20x%3D&#39;6&#39;%20y%3D&#39;5&#39;%20width%3D&#39;16&#39;%20height%3D&#39;18&#39;%20rx%3D&#39;1.5&#39;%20ry%3D&#39;1.5&#39;%2F%3E%3C%2Fsvg%3E&quot;);--ec-frm-trmIcon:url(&quot;data:image/svg+xml,%3Csvg%20xmlns%3D&#39;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&#39;%20viewBox%3D&#39;0%200%2060%2016&#39;%20preserveAspectRatio%3D&#39;xMidYMid%20meet&#39;%3E%3Ccircle%20cx%3D&#39;8&#39;%20cy%3D&#39;8&#39;%20r%3D&#39;8&#39;%2F%3E%3Ccircle%20cx%3D&#39;30&#39;%20cy%3D&#39;8&#39;%20r%3D&#39;8&#39;%2F%3E%3Ccircle%20cx%3D&#39;52&#39;%20cy%3D&#39;8&#39;%20r%3D&#39;8&#39;%2F%3E%3C%2Fsvg%3E&quot;)}.expressive-code .ec-line :where(span[style^=&#39;--&#39;]:not([class])),:root:not([data-theme=&#39;dark-plus&#39;]) .expressive-code[data-theme=&#39;dark-plus&#39;] .ec-line :where(span[style^=&#39;--&#39;]:not([class])){color:var(--0, inherit);background-color:var(--0bg, transparent);font-style:var(--0fs, inherit);font-weight:var(--0fw, inherit);text-decoration:var(--0td, inherit)}&lt;/style&gt;&lt;script type=&quot;module&quot;&gt;try{(()=&gt;{function a(e){if(!e)return;let t=e.getAttribute(&quot;tabindex&quot;)!==null,r=e.scrollWidth&gt;e.clientWidth;r&amp;&amp;!t?(e.setAttribute(&quot;tabindex&quot;,&quot;0&quot;),e.setAttribute(&quot;role&quot;,&quot;region&quot;)):!r&amp;&amp;t&amp;&amp;(e.removeAttribute(&quot;tabindex&quot;),e.removeAttribute(&quot;role&quot;))}var u=window.requestIdleCallback||(e=&gt;setTimeout(e,1)),s=window.cancelIdleCallback||clearTimeout;function l(e){let t=new Set,r,n;return new ResizeObserver(c=&gt;{c.forEach(o=&gt;t.add(o.target)),r&amp;&amp;clearTimeout(r),n&amp;&amp;s(n),r=setTimeout(()=&gt;{n&amp;&amp;s(n),n=u(()=&gt;{t.forEach(o=&gt;e(o)),t.clear()})},250)})}function i(e,t){e.querySelectorAll?.(&quot;.expressive-code pre &gt; code&quot;).forEach(r=&gt;{let n=r.parentElement;n&amp;&amp;t.observe(n)})}var d=l(a);i(document,d);var b=new MutationObserver(e=&gt;e.forEach(t=&gt;t.addedNodes.forEach(r=&gt;{i(r,d)})));b.observe(document.body,{childList:!0,subtree:!0});document.addEventListener(&quot;astro:page-load&quot;,()=&gt;{i(document,d)});})();}catch(e){console.error(&quot;[EC] tabindex-js-module failed:&quot;,e)}&lt;/script&gt;&lt;script type=&quot;module&quot;&gt;try{(()=&gt;{function i(o){let e=document.createElement(&quot;pre&quot;);Object.assign(e.style,{opacity:&quot;0&quot;,pointerEvents:&quot;none&quot;,position:&quot;absolute&quot;,overflow:&quot;hidden&quot;,left:&quot;0&quot;,top:&quot;0&quot;,width:&quot;20px&quot;,height:&quot;20px&quot;,webkitUserSelect:&quot;auto&quot;,userSelect:&quot;all&quot;}),e.ariaHidden=&quot;true&quot;,e.textContent=o,document.body.appendChild(e);let a=document.createRange();a.selectNode(e);let n=getSelection();if(!n)return!1;n.removeAllRanges(),n.addRange(a);let r=!1;try{r=document.execCommand(&quot;copy&quot;)}finally{n.removeAllRanges(),document.body.removeChild(e)}return r}async function l(o){let e=o.currentTarget,a=e.dataset,n=!1,r=a.code.replace(/&#92;u007f/g,`
`);try{await navigator.clipboard.writeText(r),n=!0}catch{n=i(r)}if(!n||e.parentNode?.querySelector(&quot;.feedback&quot;))return;let t=document.createElement(&quot;div&quot;);t.classList.add(&quot;feedback&quot;),t.append(a.copied),e.before(t),t.offsetWidth,requestAnimationFrame(()=&gt;t?.classList.add(&quot;show&quot;));let c=()=&gt;!t||t.classList.remove(&quot;show&quot;),d=()=&gt;{!t||parseFloat(getComputedStyle(t).opacity)&gt;0||(t.remove(),t=void 0)};setTimeout(c,1500),setTimeout(d,2500),e.addEventListener(&quot;blur&quot;,c),t.addEventListener(&quot;transitioncancel&quot;,d),t.addEventListener(&quot;transitionend&quot;,d)}function s(o){o.querySelectorAll?.(&quot;.expressive-code .copy button&quot;).forEach(e=&gt;e.addEventListener(&quot;click&quot;,l))}s(document);var u=new MutationObserver(o=&gt;o.forEach(e=&gt;e.addedNodes.forEach(a=&gt;{s(a)})));u.observe(document.body,{childList:!0,subtree:!0});document.addEventListener(&quot;astro:page-load&quot;,()=&gt;{s(document)});})();}catch(e){console.error(&quot;[EC] copy-js-module failed:&quot;,e)}&lt;/script&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;ts&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;class&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;Faction&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;extends&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;Schema&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;Class&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;Faction&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&#39;Faction&#39;&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;id:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;FactionId&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;name:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;Schema&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;flag:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;Flag&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;capitalId:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;Schema&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;NullOr&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;SystemObjectId&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;#ctxRef&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;WeakRef&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;Snapshot&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;set&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;Snapshot&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;#ctxRef&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;WeakRef&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;Snapshot&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4FC1FF&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;#ctxRef&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;?.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;deref&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; == &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;throw&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&#39;Context not set&#39;&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;capital&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;SystemObject&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;capitalId&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; != &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;systemObjects&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;capitalId&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; ?? &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;null&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;sectors&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;Sector&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;getSectorsWithFaction&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;systems&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;System&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;getSystemsWithFaction&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;members&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;Membership&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;getMembershipsWithOrganization&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;organizations&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#4EC9B0&quot;&gt;Membership&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;ctx&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;getMembershipsWithMember&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;this&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;export class Faction extends Schema.Class&lt;Faction&gt;(&amp;#x27;Faction&amp;#x27;)({  id: FactionId,  name: Schema.String,  flag: Flag,  capitalId: Schema.NullOr(SystemObjectId),}) {  #ctxRef: WeakRef&lt;Snapshot&gt; | null = null;  set ctx(ctx: Snapshot) {    this.#ctxRef = new WeakRef(ctx);  }  get ctx(): Snapshot {    const ctx = this.#ctxRef?.deref();    if (ctx == null) throw new Error(&amp;#x27;Context not set&amp;#x27;);    return ctx;  }  get capital(): SystemObject | null {    if (this.capitalId != null) {      return this.ctx.systemObjects[this.capitalId] ?? null;    } else {      return null;    }  }  get sectors(): Sector[] {    return this.ctx.getSectorsWithFaction(this);  }  get systems(): System[] {    return this.ctx.getSystemsWithFaction(this);  }  get members(): Membership[] {    return this.ctx.getMembershipsWithOrganization(this);  }  get organizations(): Membership[] {    return this.ctx.getMembershipsWithMember(this);  }}&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The methods simplify a lot of later data processing (previously, these were all plain objects with no methods). In the future I&#39;ll also use Effect for the data processing pipelines, and for automatic data migration between StellarMaps versions.&lt;/p&gt;
&lt;h1&gt;Beyond Development&lt;/h1&gt;
&lt;p&gt;Where&#39;s all my time gone otherwise this month?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Work is busy, with my employer in the process of getting acquired&lt;/li&gt;
&lt;li&gt;House work is also busy, with the final stage of an insurance claim and early stage of a kitchen remodel&lt;/li&gt;
&lt;li&gt;It&#39;s gardening season here in Minnesota
&lt;ul&gt;
&lt;li&gt;Harvesting strawberries and raspberries&lt;/li&gt;
&lt;li&gt;Establishing a pollinator lawn, which mostly means lots of weeding&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Studying Chinese and Japanese in preparation for autumn travel
&lt;ul&gt;
&lt;li&gt;If anyone in Tokyo or Shanghai wants to meet up, reach out!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Morrowind has been my chill-out game this month. That game holds up, and the &lt;a href=&quot;https://openmw.org&quot;&gt;OpenMW&lt;/a&gt; project is really impressive&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Fri, 04 Jul 2025 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/scoop-2025-07/</guid>
    </item>
    <item>
      <title>Scoop of Oatmeal, June &#39;25</title>
      <link>https://oatmeal.gg/blog/scoop-2025-06/</link>
      <description>&lt;p&gt;It&#39;s past time for an update here. Going forward, I&#39;ll aim for monthly updates here about what I&#39;ve been working on generally, rather than tied to any single project. This post, recapping nearly a year, is kind of a wall of text. Future posts will hopefully be more colorful with images and code snippets.&lt;/p&gt;
&lt;h2&gt;StellarMaps&lt;/h2&gt;
&lt;p&gt;StellarMaps continues to be my main focus. I&#39;ve released one non-patch release, and done lots of work on the underlying technology to lay the foundations for its future.&lt;/p&gt;
&lt;h3&gt;v0.12: Modes, Legends, and System Maps&lt;/h3&gt;
&lt;p&gt;In September, I released v0.12 of StellarMaps. This introduced 3 major features.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Map Modes&lt;/strong&gt; color-code countries and systems according to various data and relationships. Map modes are a concept from Stellaris, and had been requested multiple times for StellarMaps. I wanted to go a step further than Stellaris, which generally only changes the colors of entire countries, so I added the population map mode which displays data solar-system level.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Legends&lt;/strong&gt; were a natural fit to release alongside map modes. There&#39;s not much point in color-coding things if you can&#39;t tell what the different colors mean. I had also noticed people often asking what the various system icons (eg capital, sector capital) meant when others shared maps online, so legends help address that too.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Solar System Maps&lt;/strong&gt; show the planets, moons, etc in a single solar system. This feature had not been requested much, but it has turned out to be quite popular with the AAR community. The development for this feature was supported by an anonymous sponsor. That&#39;s the first (hopefully not last) instance of me making some money from StellarMaps development! Note that this is not a premium feature or anything like that; it is free and open source just like the rest of StellarMaps.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Tech Upgrades&lt;/h3&gt;
&lt;p&gt;For the upcoming v0.13, I first worked on major updates to the code libraries StellarMaps is built upon. Tauri (the desktop app framework) was upgraded from 1 to 2. Svelte (the UI framework) was upgraded from 4 to 5. And finally Skeleton (the style and component library) was upgraded from 2 to 3.&lt;/p&gt;
&lt;p&gt;Along with the Tauri update, I&#39;ve also worked on an Electron version of the app for Linux. Essentially, Electron provides a more performant and stable UI at the cost of a larger install size. Once this is released, I&#39;ll write a longer article about why and how.&lt;/p&gt;
&lt;h3&gt;De-Stellaris&lt;/h3&gt;
&lt;p&gt;I&#39;ve received many requests from people who want to use StellarMaps to create maps for fiction, world-building, RPGs, etc, completely unrelated to Stellaris. I&#39;ve begun the work to make that possible. The first step in that is to separate StellarMaps data model from the Stellaris save file format. Today, StellarMaps is a program that opens Stellaris save files. Next release, StellarMaps will have it&#39;s own concept of &lt;em&gt;projects&lt;/em&gt;, which contain multiple &lt;em&gt;snapshots&lt;/em&gt; of a galaxy, that are imported from Stellaris saves. This will bring performance improvements, time-lapses, and quality-of-life for modded games. Longer term, this provides the groundwork to create projects from scratch, or potentially import from other sources (other games, real astronomical data)&lt;/p&gt;
&lt;h2&gt;Stellaris Mod Updates&lt;/h2&gt;
&lt;p&gt;Stellaris released a massive update in May, and it took longer than usual to update my mods. With the overhaul to trade in Stellaris, I retired my mod Cross Border Trade. I also created a new mod &lt;a href=&quot;https://steamcommunity.com/sharedfiles/filedetails/?id=3476554363&quot;&gt;Intuitive Habitables Slider&lt;/a&gt;, which replaces my Fewer Habitable Planets series of mods.&lt;/p&gt;
&lt;h2&gt;7DRL: 5 Letter Rogue&lt;/h2&gt;
&lt;p&gt;In March, I participated in the &lt;a href=&quot;https://itch.io/jam/7drl-challenge-2025&quot;&gt;7 Day Roguelike Challenge (7DRL)&lt;/a&gt;, a casual and low-stakes game jam. My entry, &lt;a href=&quot;https://oatmealproblem.itch.io/5-letter-rogue&quot;&gt;5 Letter Rogue&lt;/a&gt; is a mashup of traditional roguelike and word game, which has the player collecting letters from enemies and then using them to type spells. My goal for the jam was to explore that concept and see if it has potential. From that perspective, it was a success, but overall I don&#39;t think it&#39;s a very good game in its current form. Now that the results are in from the judges, I want to revisit it for some minor balance and QoL updates. Longer term, I might expand upon the game, but I&#39;ll save those thoughts for a future blog post.&lt;/p&gt;
&lt;h2&gt;Open Source Contributions&lt;/h2&gt;
&lt;p&gt;I contributed &lt;a href=&quot;https://shiki.style/packages/colorized-brackets&quot;&gt;colorized brackets to Shiki&lt;/a&gt; and improved support for Shiki transformers in &lt;a href=&quot;https://expressive-code.com&quot;&gt;Expressive Code&lt;/a&gt; (so, for example, you can use colorized brackets in Expressive Code). Both of those are now in use on this blog.&lt;/p&gt;</description>
      <pubDate>Sun, 08 Jun 2025 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/scoop-2025-06/</guid>
    </item>
    <item>
      <title>VSCode-style Colored Brackets for Shiki</title>
      <link>https://oatmeal.gg/blog/shiki-colored-brackets/</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://shiki.style&quot;&gt;Shiki&lt;/a&gt; is a popular syntax highlighter, powered by the same engine as VSCode. However, colored brackets are not part of the main syntax highlighting engine, so they were missing from Shiki. A few months, I worked on a plugin for this, which is now officially part of Shiki via &lt;code&gt;@shikijs/colorized-brackets&lt;/code&gt;. I&#39;ll walk through the setup to use that in an Eleventy blog.&lt;/p&gt;
&lt;h2&gt;Dependencies&lt;/h2&gt;
&lt;p&gt;First off, we&#39;ll need to install some dependencies:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;style&gt;.expressive-code{font-family:var(--ec-uiFontFml);font-size:var(--ec-uiFontSize);font-weight:var(--ec-uiFontWg);line-height:var(--ec-uiLineHt);text-size-adjust:none;-webkit-text-size-adjust:none}.expressive-code *:not(:is(svg, svg *)){all:revert;box-sizing:border-box}.expressive-code pre{display:flex;margin:0;padding:0;border:var(--ec-brdWd) solid var(--ec-brdCol);border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));background:var(--ec-codeBg)}.expressive-code pre:focus-visible{outline:3px solid var(--ec-focusBrd);outline-offset:-3px}.expressive-code pre &gt; code{all:unset;display:block;flex:1 0 100%;padding:var(--ec-codePadBlk) 0;color:var(--ec-codeFg);font-family:var(--ec-codeFontFml);font-size:var(--ec-codeFontSize);font-weight:var(--ec-codeFontWg);line-height:var(--ec-codeLineHt)}.expressive-code pre{overflow-x:auto}.expressive-code pre.wrap .ec-line .code{white-space:pre-wrap;overflow-wrap:break-word;min-width:min(20ch, var(--ecMaxLine, 20ch))}.expressive-code pre.wrap .ec-line .code span.indent{white-space:pre}.expressive-code pre::-webkit-scrollbar,.expressive-code pre::-webkit-scrollbar-track{background-color:inherit;border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));border-top-left-radius:0;border-top-right-radius:0}.expressive-code pre::-webkit-scrollbar-thumb{background-color:var(--ec-sbThumbCol);border:4px solid transparent;background-clip:content-box;border-radius:10px}.expressive-code pre::-webkit-scrollbar-thumb:hover{background-color:var(--ec-sbThumbHoverCol)}.expressive-code .ec-line{direction:ltr;unicode-bidi:isolate;display:grid;grid-template-areas:&#39;gutter code&#39;;grid-template-columns:auto 1fr;position:relative}.expressive-code .ec-line .gutter{grid-area:gutter;color:var(--ec-gtrFg)}.expressive-code .ec-line .gutter &gt; *{pointer-events:none;user-select:none;-webkit-user-select:none}.expressive-code .ec-line .gutter ~ .code{--ecLineBrdCol:var(--ec-gtrBrdCol)}.expressive-code .ec-line.highlight .gutter{color:var(--ec-gtrHlFg)}.expressive-code .ec-line .code{grid-area:code;position:relative;box-sizing:content-box;padding-inline-start:calc(var(--ecIndent, 0ch) + var(--ec-codePadInl) - var(--ecGtrBrdWd));padding-inline-end:var(--ec-codePadInl);text-indent:calc(var(--ecIndent, 0ch) * -1)}.expressive-code .ec-line .code::before,.expressive-code .ec-line .code::after,.expressive-code .ec-line .code :where(*){text-indent:0}.expressive-code .ec-line .code{--ecGtrBrdWd:var(--ec-gtrBrdWd);border-inline-start:var(--ecGtrBrdWd) solid var(--ecLineBrdCol, transparent)}.expressive-code .sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0}.expressive-code .ec-line.mark{--tmLineBgCol:var(--ec-tm-markBg)}.expressive-code .ec-line.mark .code{--ecLineBrdCol:var(--ec-tm-markBrdCol)}.expressive-code .ec-line.ins{--tmLineBgCol:var(--ec-tm-insBg);--tmLabel:var(--ec-tm-insDiffIndContent)}.expressive-code .ec-line.ins .code{--ecLineBrdCol:var(--ec-tm-insBrdCol)}.expressive-code .ec-line.ins .code::before{color:var(--ec-tm-insDiffIndCol)}.expressive-code .ec-line.del{--tmLineBgCol:var(--ec-tm-delBg);--tmLabel:var(--ec-tm-delDiffIndContent)}.expressive-code .ec-line.del .code{--ecLineBrdCol:var(--ec-tm-delBrdCol)}.expressive-code .ec-line.del .code::before{color:var(--ec-tm-delDiffIndCol)}.expressive-code .ec-line.mark,.expressive-code .ec-line.ins,.expressive-code .ec-line.del{background:var(--tmLineBgCol)}.expressive-code .ec-line.mark .code,.expressive-code .ec-line.ins .code,.expressive-code .ec-line.del .code{--ecGtrBrdWd:var(--ec-tm-lineMarkerAccentWd)}.expressive-code .ec-line.mark .code::before,.expressive-code .ec-line.ins .code::before,.expressive-code .ec-line.del .code::before{display:block;position:absolute;left:0;box-sizing:border-box;content:var(--tmLabel, &#39; &#39;);padding-inline-start:var(--ec-tm-lineDiffIndMargLeft);text-align:center;white-space:pre}.expressive-code .ec-line.mark.tm-label .code::before,.expressive-code .ec-line.ins.tm-label .code::before,.expressive-code .ec-line.del.tm-label .code::before{background:var(--ecLineBrdCol);padding:0 calc(var(--ec-tm-lineMarkerLabelPadInl) + var(--ec-tm-lineMarkerAccentWd)) 0 var(--ec-tm-lineMarkerLabelPadInl);color:var(--ec-tm-lineMarkerLabelCol)}.expressive-code .ec-line mark{--tmInlineBgCol:var(--ec-tm-markBg);--tmInlineBrdCol:var(--ec-tm-markBrdCol)}.expressive-code .ec-line ins{--tmInlineBgCol:var(--ec-tm-insBg);--tmInlineBrdCol:var(--ec-tm-insBrdCol)}.expressive-code .ec-line del{--tmInlineBgCol:var(--ec-tm-delBg);--tmInlineBrdCol:var(--ec-tm-delBrdCol)}.expressive-code .ec-line mark,.expressive-code .ec-line ins,.expressive-code .ec-line del{all:unset;display:inline-block;position:relative;--tmBrdL:var(--ec-tm-inlMarkerBrdWd);--tmBrdR:var(--ec-tm-inlMarkerBrdWd);--tmRadL:var(--ec-tm-inlMarkerBrdRad);--tmRadR:var(--ec-tm-inlMarkerBrdRad);margin-inline:0.025rem;padding-inline:var(--ec-tm-inlMarkerPad);border-radius:var(--tmRadL) var(--tmRadR) var(--tmRadR) var(--tmRadL);background:var(--tmInlineBgCol);background-clip:padding-box}.expressive-code .ec-line mark.open-start,.expressive-code .ec-line ins.open-start,.expressive-code .ec-line del.open-start{margin-inline-start:0;padding-inline-start:0;--tmBrdL:0px;--tmRadL:0}.expressive-code .ec-line mark.open-end,.expressive-code .ec-line ins.open-end,.expressive-code .ec-line del.open-end{margin-inline-end:0;padding-inline-end:0;--tmBrdR:0px;--tmRadR:0}.expressive-code .ec-line mark::before,.expressive-code .ec-line ins::before,.expressive-code .ec-line del::before{content:&#39;&#39;;position:absolute;pointer-events:none;display:inline-block;inset:0;border-radius:var(--tmRadL) var(--tmRadR) var(--tmRadR) var(--tmRadL);border:var(--ec-tm-inlMarkerBrdWd) solid var(--tmInlineBrdCol);border-inline-width:var(--tmBrdL) var(--tmBrdR)}.expressive-code .frame{all:unset;position:relative;display:block;--header-border-radius:calc(var(--ec-brdRad) + var(--ec-brdWd));--tab-border-radius:calc(var(--ec-frm-edTabBrdRad) + var(--ec-brdWd));--button-spacing:0.4rem;--code-background:var(--ec-frm-edBg);border-radius:var(--header-border-radius);box-shadow:var(--ec-frm-frameBoxShdCssVal)}.expressive-code .frame .header{display:none;z-index:1;position:relative;border-radius:var(--header-border-radius) var(--header-border-radius) 0 0}.expressive-code .frame.has-title pre,.expressive-code .frame.has-title code,.expressive-code .frame.is-terminal pre,.expressive-code .frame.is-terminal code{border-top:none;border-top-left-radius:0;border-top-right-radius:0}.expressive-code .frame .title:empty:before{content:&#39;&#92;a0&#39;}.expressive-code .frame.has-title:not(.is-terminal){--button-spacing:calc(1.9rem + 2 * (var(--ec-uiPadBlk) + var(--ec-frm-edActTabIndHt)))}.expressive-code .frame.has-title:not(.is-terminal) .title{position:relative;color:var(--ec-frm-edActTabFg);background:var(--ec-frm-edActTabBg);background-clip:padding-box;margin-block-start:var(--ec-frm-edTabsMargBlkStart);padding:calc(var(--ec-uiPadBlk) + var(--ec-frm-edActTabIndHt)) var(--ec-uiPadInl);border:var(--ec-brdWd) solid var(--ec-frm-edActTabBrdCol);border-radius:var(--tab-border-radius) var(--tab-border-radius) 0 0;border-bottom:none;overflow:hidden}.expressive-code .frame.has-title:not(.is-terminal) .title::after{content:&#39;&#39;;position:absolute;pointer-events:none;inset:0;border-top:var(--ec-frm-edActTabIndHt) solid var(--ec-frm-edActTabIndTopCol);border-bottom:var(--ec-frm-edActTabIndHt) solid var(--ec-frm-edActTabIndBtmCol)}.expressive-code .frame.has-title:not(.is-terminal) .header{display:flex;background:linear-gradient(to top, var(--ec-frm-edTabBarBrdBtmCol) var(--ec-brdWd), transparent var(--ec-brdWd)),linear-gradient(var(--ec-frm-edTabBarBg), var(--ec-frm-edTabBarBg));background-repeat:no-repeat;padding-inline-start:var(--ec-frm-edTabsMargInlStart)}.expressive-code .frame.has-title:not(.is-terminal) .header::before{content:&#39;&#39;;position:absolute;pointer-events:none;inset:0;border:var(--ec-brdWd) solid var(--ec-frm-edTabBarBrdCol);border-radius:inherit;border-bottom:none}.expressive-code .frame.is-terminal{--button-spacing:calc(1.9rem + var(--ec-brdWd) + 2 * var(--ec-uiPadBlk));--code-background:var(--ec-frm-trmBg)}.expressive-code .frame.is-terminal .header{display:flex;align-items:center;justify-content:center;padding-block:var(--ec-uiPadBlk);padding-block-end:calc(var(--ec-uiPadBlk) + var(--ec-brdWd));position:relative;font-weight:500;letter-spacing:0.025ch;color:var(--ec-frm-trmTtbFg);background:var(--ec-frm-trmTtbBg);border:var(--ec-brdWd) solid var(--ec-brdCol);border-bottom:none}.expressive-code .frame.is-terminal .header::before{content:&#39;&#39;;position:absolute;pointer-events:none;left:var(--ec-uiPadInl);width:2.1rem;height:0.56rem;line-height:0;background-color:var(--ec-frm-trmTtbDotsFg);opacity:var(--ec-frm-trmTtbDotsOpa);-webkit-mask-image:var(--ec-frm-trmIcon);-webkit-mask-repeat:no-repeat;mask-image:var(--ec-frm-trmIcon);mask-repeat:no-repeat}.expressive-code .frame.is-terminal .header::after{content:&#39;&#39;;position:absolute;pointer-events:none;inset:0;border-bottom:var(--ec-brdWd) solid var(--ec-frm-trmTtbBrdBtmCol)}.expressive-code .frame pre{background:var(--code-background)}.expressive-code .copy{display:flex;gap:0.25rem;flex-direction:row;position:absolute;inset-block-start:calc(var(--ec-brdWd) + var(--button-spacing));inset-inline-end:calc(var(--ec-brdWd) + var(--ec-uiPadInl) / 2)}@media (scripting: none){.expressive-code .copy{display:none}}.expressive-code .copy{direction:ltr;unicode-bidi:isolate}.expressive-code .copy button{position:relative;align-self:flex-end;margin:0;padding:0;border:none;border-radius:0.2rem;z-index:1;cursor:pointer;transition-property:opacity, background, border-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.25, 0.46, 0.45, 0.94);width:2.5rem;height:2.5rem;background:var(--code-background);opacity:0.75}.expressive-code .copy button div{position:absolute;inset:0;border-radius:inherit;background:var(--ec-frm-inlBtnBg);opacity:var(--ec-frm-inlBtnBgIdleOpa);transition-property:inherit;transition-duration:inherit;transition-timing-function:inherit}.expressive-code .copy button::before{content:&#39;&#39;;position:absolute;pointer-events:none;inset:0;border-radius:inherit;border:var(--ec-brdWd) solid var(--ec-frm-inlBtnBrd);opacity:var(--ec-frm-inlBtnBrdOpa)}.expressive-code .copy button::after{content:&#39;&#39;;position:absolute;pointer-events:none;inset:0;background-color:var(--ec-frm-inlBtnFg);-webkit-mask-image:var(--ec-frm-copyIcon);-webkit-mask-repeat:no-repeat;mask-image:var(--ec-frm-copyIcon);mask-repeat:no-repeat;margin:0.475rem;line-height:0}.expressive-code .copy button:hover,.expressive-code .copy button:focus:focus-visible{opacity:1}.expressive-code .copy button:hover div,.expressive-code .copy button:focus:focus-visible div{opacity:var(--ec-frm-inlBtnBgHoverOrFocusOpa)}.expressive-code .copy button:active{opacity:1}.expressive-code .copy button:active div{opacity:var(--ec-frm-inlBtnBgActOpa)}.expressive-code .copy .feedback{--tooltip-arrow-size:0.35rem;--tooltip-bg:var(--ec-frm-tooltipSuccessBg);color:var(--ec-frm-tooltipSuccessFg);pointer-events:none;user-select:none;-webkit-user-select:none;position:relative;align-self:center;background-color:var(--tooltip-bg);z-index:99;padding:0.125rem 0.75rem;border-radius:0.2rem;margin-inline-end:var(--tooltip-arrow-size);opacity:0;transition-property:opacity, transform;transition-duration:0.2s;transition-timing-function:ease-in-out;transform:translate3d(0, 0.25rem, 0)}.expressive-code .copy .feedback::after{content:&#39;&#39;;position:absolute;pointer-events:none;top:calc(50% - var(--tooltip-arrow-size));inset-inline-end:calc(-2 * (var(--tooltip-arrow-size) - 0.5px));border:var(--tooltip-arrow-size) solid transparent;border-inline-start-color:var(--tooltip-bg)}.expressive-code .copy .feedback.show{opacity:1;transform:translate3d(0, 0, 0)}@media (hover: hover){.expressive-code{}.expressive-code .copy button{opacity:0;width:2rem;height:2rem}.expressive-code .frame:hover .copy button:not(:hover),.expressive-code .frame:focus-within :focus-visible ~ .copy button:not(:hover),.expressive-code .frame .copy .feedback.show ~ button:not(:hover){opacity:0.75}}.expressive-code :nth-child(1 of .ec-line) .code{padding-inline-end:calc(2rem + var(--ec-codePadInl))}:root,:root:not([data-theme=&#39;dark-plus&#39;]) .expressive-code[data-theme=&#39;dark-plus&#39;]{--ec-brdRad:0.3rem;--ec-brdWd:1.5px;--ec-brdCol:var(--pico-blockquote-border-color);--ec-codeFontFml:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,&#39;Liberation Mono&#39;,&#39;Courier New&#39;,monospace;--ec-codeFontSize:0.85rem;--ec-codeFontWg:400;--ec-codeLineHt:1.65;--ec-codePadBlk:1rem;--ec-codePadInl:1.35rem;--ec-codeBg:var(--pico-code-background-color);--ec-codeFg:#d4d4d4;--ec-codeSelBg:#264f78;--ec-gtrFg:#858585;--ec-gtrBrdCol:#85858533;--ec-gtrBrdWd:1.5px;--ec-gtrHlFg:#c6c6c6;--ec-uiFontFml:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,&#39;Segoe UI&#39;,Roboto,&#39;Helvetica Neue&#39;,Arial,&#39;Noto Sans&#39;,sans-serif,&#39;Apple Color Emoji&#39;,&#39;Segoe UI Emoji&#39;,&#39;Segoe UI Symbol&#39;,&#39;Noto Color Emoji&#39;;--ec-uiFontSize:0.9rem;--ec-uiFontWg:400;--ec-uiLineHt:1.65;--ec-uiPadBlk:0.25rem;--ec-uiPadInl:1rem;--ec-uiSelBg:#0078d4;--ec-uiSelFg:#ffffff;--ec-focusBrd:#007fd4;--ec-sbThumbCol:#79797966;--ec-sbThumbHoverCol:#646464b2;--ec-tm-lineMarkerAccentMarg:0rem;--ec-tm-lineMarkerAccentWd:0.15rem;--ec-tm-lineMarkerLabelPadInl:0.2rem;--ec-tm-lineMarkerLabelCol:white;--ec-tm-lineDiffIndMargLeft:0.3rem;--ec-tm-inlMarkerBrdWd:1.5px;--ec-tm-inlMarkerBrdRad:0.2rem;--ec-tm-inlMarkerPad:0.15rem;--ec-tm-insDiffIndContent:&#39;+&#39;;--ec-tm-delDiffIndContent:&#39;-&#39;;--ec-tm-markBg:#264a8980;--ec-tm-markBrdCol:#5570b3d0;--ec-tm-insBg:#26561c80;--ec-tm-insBrdCol:#4e7e41d0;--ec-tm-insDiffIndCol:#7eb070d0;--ec-tm-delBg:#81322b80;--ec-tm-delBrdCol:#ae594fd0;--ec-tm-delDiffIndCol:#e68a7ed0;--ec-frm-shdCol:#0000005b;--ec-frm-frameBoxShdCssVal:0.1rem 0.1rem 0.2rem #0000005b;--ec-frm-edActTabBg:var(--pico-code-background-color);--ec-frm-edActTabFg:#ffffff;--ec-frm-edActTabBrdCol:transparent;--ec-frm-edActTabIndHt:1.5px;--ec-frm-edActTabIndTopCol:null;--ec-frm-edActTabIndBtmCol:null;--ec-frm-edTabsMargInlStart:0;--ec-frm-edTabsMargBlkStart:0;--ec-frm-edTabBrdRad:0.3rem;--ec-frm-edTabBarBg:var(--pico-background-color);--ec-frm-edTabBarBrdCol:var(--pico-blockquote-border-color);--ec-frm-edTabBarBrdBtmCol:transparent;--ec-frm-edBg:var(--pico-code-background-color);--ec-frm-trmTtbFg:#cccccc;--ec-frm-trmTtbDotsFg:#cccccc;--ec-frm-trmTtbDotsOpa:0.15;--ec-frm-trmTtbBg:var(--pico-background-color);--ec-frm-trmTtbBrdBtmCol:#000000bf;--ec-frm-trmBg:var(--pico-code-background-color);--ec-frm-inlBtnFg:#d4d4d4;--ec-frm-inlBtnBg:#d4d4d4;--ec-frm-inlBtnBgIdleOpa:0;--ec-frm-inlBtnBgHoverOrFocusOpa:0.2;--ec-frm-inlBtnBgActOpa:0.3;--ec-frm-inlBtnBrd:#d4d4d4;--ec-frm-inlBtnBrdOpa:0.4;--ec-frm-tooltipSuccessBg:#098656;--ec-frm-tooltipSuccessFg:white;--ec-frm-copyIcon:url(&quot;data:image/svg+xml,%3Csvg%20xmlns%3D&#39;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&#39;%20viewBox%3D&#39;0%200%2024%2024&#39;%20fill%3D&#39;none&#39;%20stroke%3D&#39;black&#39;%20stroke-width%3D&#39;1.75&#39;%3E%3Cpath%20d%3D&#39;M3%2019a2%202%200%200%201-1-2V2a2%202%200%200%201%201-1h13a2%202%200%200%201%202%201&#39;%2F%3E%3Crect%20x%3D&#39;6&#39;%20y%3D&#39;5&#39;%20width%3D&#39;16&#39;%20height%3D&#39;18&#39;%20rx%3D&#39;1.5&#39;%20ry%3D&#39;1.5&#39;%2F%3E%3C%2Fsvg%3E&quot;);--ec-frm-trmIcon:url(&quot;data:image/svg+xml,%3Csvg%20xmlns%3D&#39;http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg&#39;%20viewBox%3D&#39;0%200%2060%2016&#39;%20preserveAspectRatio%3D&#39;xMidYMid%20meet&#39;%3E%3Ccircle%20cx%3D&#39;8&#39;%20cy%3D&#39;8&#39;%20r%3D&#39;8&#39;%2F%3E%3Ccircle%20cx%3D&#39;30&#39;%20cy%3D&#39;8&#39;%20r%3D&#39;8&#39;%2F%3E%3Ccircle%20cx%3D&#39;52&#39;%20cy%3D&#39;8&#39;%20r%3D&#39;8&#39;%2F%3E%3C%2Fsvg%3E&quot;)}.expressive-code .ec-line :where(span[style^=&#39;--&#39;]:not([class])),:root:not([data-theme=&#39;dark-plus&#39;]) .expressive-code[data-theme=&#39;dark-plus&#39;] .ec-line :where(span[style^=&#39;--&#39;]:not([class])){color:var(--0, inherit);background-color:var(--0bg, transparent);font-style:var(--0fs, inherit);font-weight:var(--0fw, inherit);text-decoration:var(--0td, inherit)}&lt;/style&gt;&lt;script type=&quot;module&quot;&gt;try{(()=&gt;{function a(e){if(!e)return;let t=e.getAttribute(&quot;tabindex&quot;)!==null,r=e.scrollWidth&gt;e.clientWidth;r&amp;&amp;!t?(e.setAttribute(&quot;tabindex&quot;,&quot;0&quot;),e.setAttribute(&quot;role&quot;,&quot;region&quot;)):!r&amp;&amp;t&amp;&amp;(e.removeAttribute(&quot;tabindex&quot;),e.removeAttribute(&quot;role&quot;))}var u=window.requestIdleCallback||(e=&gt;setTimeout(e,1)),s=window.cancelIdleCallback||clearTimeout;function l(e){let t=new Set,r,n;return new ResizeObserver(c=&gt;{c.forEach(o=&gt;t.add(o.target)),r&amp;&amp;clearTimeout(r),n&amp;&amp;s(n),r=setTimeout(()=&gt;{n&amp;&amp;s(n),n=u(()=&gt;{t.forEach(o=&gt;e(o)),t.clear()})},250)})}function i(e,t){e.querySelectorAll?.(&quot;.expressive-code pre &gt; code&quot;).forEach(r=&gt;{let n=r.parentElement;n&amp;&amp;t.observe(n)})}var d=l(a);i(document,d);var b=new MutationObserver(e=&gt;e.forEach(t=&gt;t.addedNodes.forEach(r=&gt;{i(r,d)})));b.observe(document.body,{childList:!0,subtree:!0});document.addEventListener(&quot;astro:page-load&quot;,()=&gt;{i(document,d)});})();}catch(e){console.error(&quot;[EC] tabindex-js-module failed:&quot;,e)}&lt;/script&gt;&lt;script type=&quot;module&quot;&gt;try{(()=&gt;{function i(o){let e=document.createElement(&quot;pre&quot;);Object.assign(e.style,{opacity:&quot;0&quot;,pointerEvents:&quot;none&quot;,position:&quot;absolute&quot;,overflow:&quot;hidden&quot;,left:&quot;0&quot;,top:&quot;0&quot;,width:&quot;20px&quot;,height:&quot;20px&quot;,webkitUserSelect:&quot;auto&quot;,userSelect:&quot;all&quot;}),e.ariaHidden=&quot;true&quot;,e.textContent=o,document.body.appendChild(e);let a=document.createRange();a.selectNode(e);let n=getSelection();if(!n)return!1;n.removeAllRanges(),n.addRange(a);let r=!1;try{r=document.execCommand(&quot;copy&quot;)}finally{n.removeAllRanges(),document.body.removeChild(e)}return r}async function l(o){let e=o.currentTarget,a=e.dataset,n=!1,r=a.code.replace(/&#92;u007f/g,`
`);try{await navigator.clipboard.writeText(r),n=!0}catch{n=i(r)}if(!n||e.parentNode?.querySelector(&quot;.feedback&quot;))return;let t=document.createElement(&quot;div&quot;);t.classList.add(&quot;feedback&quot;),t.append(a.copied),e.before(t),t.offsetWidth,requestAnimationFrame(()=&gt;t?.classList.add(&quot;show&quot;));let c=()=&gt;!t||t.classList.remove(&quot;show&quot;),d=()=&gt;{!t||parseFloat(getComputedStyle(t).opacity)&gt;0||(t.remove(),t=void 0)};setTimeout(c,1500),setTimeout(d,2500),e.addEventListener(&quot;blur&quot;,c),t.addEventListener(&quot;transitioncancel&quot;,d),t.addEventListener(&quot;transitionend&quot;,d)}function s(o){o.querySelectorAll?.(&quot;.expressive-code .copy button&quot;).forEach(e=&gt;e.addEventListener(&quot;click&quot;,l))}s(document);var u=new MutationObserver(o=&gt;o.forEach(e=&gt;e.addedNodes.forEach(a=&gt;{s(a)})));u.observe(document.body,{childList:!0,subtree:!0});document.addEventListener(&quot;astro:page-load&quot;,()=&gt;{s(document)});})();}catch(e){console.error(&quot;[EC] copy-js-module failed:&quot;,e)}&lt;/script&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;npm&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;i&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;-D&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;@shikijs/colorized-brackets&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;unified&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;remark-parse&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;remark-rehype&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;rehype-stringify&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;rehype-expressive-code&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;npm i -D @shikijs/colorized-brackets unified remark-parse remark-rehype rehype-stringify rehype-expressive-code&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@shikijs/colorized-brackets&lt;/code&gt;: Shiki plugin for colored brackets&lt;/li&gt;
&lt;li&gt;&lt;code&gt;unified&lt;/code&gt;: an ecosystem for parsing and transforming content&lt;/li&gt;
&lt;li&gt;&lt;code&gt;remark-parse&lt;/code&gt;: unified plugin to parse markdown&lt;/li&gt;
&lt;li&gt;&lt;code&gt;remark-rehype&lt;/code&gt;: unified plugin to turn markdown into html&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rehype-stringify&lt;/code&gt;: unified plugin to turn html into string&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rehype-expressive-code&lt;/code&gt;: unified plugin for &lt;a href=&quot;https://expressive-code.com&quot;&gt;Expressive Code&lt;/a&gt;, a wrapper around Shiki with extra features&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Config&lt;/h2&gt;
&lt;p&gt;To start, we need to import those dependencies we just installed, in our &lt;code&gt;eleventy.config.js&lt;/code&gt; file:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;eleventy.config.js&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;transformerColorizedBrackets&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;@shikijs/colorized-brackets&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;unified&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;unified&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;remarkParse&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;remark-parse&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;remarkRehype&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;remark-rehype&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;rehypeStringify&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;rehype-stringify&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;rehypeExpressiveCode&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;rehype-expressive-code&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;import { transformerColorizedBrackets } from &amp;#x22;@shikijs/colorized-brackets&amp;#x22;;import { unified } from &amp;#x22;unified&amp;#x22;;import remarkParse from &amp;#x22;remark-parse&amp;#x22;;import remarkRehype from &amp;#x22;remark-rehype&amp;#x22;;import rehypeStringify from &amp;#x22;rehype-stringify&amp;#x22;;import rehypeExpressiveCode from &amp;#x22;rehype-expressive-code&amp;#x22;;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;and then set configure eleventy to use &lt;code&gt;unified&lt;/code&gt;/&lt;code&gt;remark&lt;/code&gt;/&lt;code&gt;rehype&lt;/code&gt; for markdown files:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;eleventy.config.js&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;eleventyConfig&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;setLibrary&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;md&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;render&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;pageContext&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;unified&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;remarkParse&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#74A061&quot;&gt;// parse markdown&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;remarkRehype&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#74A061&quot;&gt;// convert markdown AST to html AST&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;rehypeExpressiveCode&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#74A061&quot;&gt;// perform syntax highlighting on code blocks&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;themes:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;dark-plus&quot;&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#74A061&quot;&gt;// syntax highlighting theme, see https://expressive-code.com/guides/themes/ for more&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;shiki:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;transformers:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;transformerColorizedBrackets&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#74A061&quot;&gt;// this enables colored brackets for Shiki&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;rehypeStringify&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#74A061&quot;&gt;// convert html AST to string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;pageContext&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;eleventyConfig&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;process&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;  eleventyConfig.setLibrary(&amp;#x22;md&amp;#x22;, {    render: async (content, pageContext) =&gt; {      return await unified()        .use(remarkParse) // parse markdown        .use(remarkRehype) // convert markdown AST to html AST        .use(rehypeExpressiveCode, { // perform syntax highlighting on code blocks          themes: [&amp;#x22;dark-plus&amp;#x22;], // syntax highlighting theme, see https://expressive-code.com/guides/themes/ for more          shiki: { transformers: [transformerColorizedBrackets()] }, // this enables colored brackets for Shiki        })        .use(rehypeStringify) // convert html AST to string        .data({          pageContext,          eleventyConfig,        })        .process(content);    },  });&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;With some additional Expressive Code configuration to better match my &lt;a href=&quot;https://picocss.com/&quot;&gt;Pico CSS&lt;/a&gt; theme, here&#39;s my complete config for syntax highlighting:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;eleventy.config.js&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;js&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#74A061&quot;&gt;// other imports...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;transformerColorizedBrackets&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;@shikijs/colorized-brackets&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;unified&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;unified&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;remarkParse&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;remark-parse&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;remarkRehype&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;remark-rehype&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;rehypeStringify&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;rehype-stringify&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;import&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;rehypeExpressiveCode&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;rehype-expressive-code&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;export&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;default&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;function&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;eleventyConfig&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#74A061&quot;&gt;// other config...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4FC1FF&quot;&gt;codeBackground&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;`var(--pico-code-background-color)`&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4FC1FF&quot;&gt;codeBackgroundLighter&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;var(--pico-background-color)&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;const&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#4FC1FF&quot;&gt;codeBorder&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;var(--pico-blockquote-border-color)&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;eleventyConfig&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;setLibrary&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;md&quot;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;render&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;async&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;pageContext&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--0:#569CD6&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;return&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#C586C0&quot;&gt;await&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;unified&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;remarkParse&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;remarkRehype&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;rehypeExpressiveCode&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;themes:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#CE9178&quot;&gt;&quot;dark-plus&quot;&lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;styleOverrides:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;codeBackground:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;codeBackground&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;borderColor:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;codeBorder&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;frames:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;editorActiveTabBackground:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;codeBackground&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;editorTabBarBackground:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;codeBackgroundLighter&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;terminalBackground:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;codeBackground&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;terminalTitlebarBackground:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;codeBackgroundLighter&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;shiki:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;{&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;transformers:&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;transformerColorizedBrackets&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;]&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;rehypeStringify&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;pageContext&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;eleventyConfig&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;--0:#DCDCAA&quot;&gt;process&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--0:#9CDCFE&quot;&gt;content&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#179FFF&quot;&gt;}&lt;/span&gt;&lt;span style=&quot;--0:#DA70D6&quot;&gt;)&lt;/span&gt;&lt;span style=&quot;--0:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#FFD700&quot;&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;// other imports...import { transformerColorizedBrackets } from &amp;#x22;@shikijs/colorized-brackets&amp;#x22;;import { unified } from &amp;#x22;unified&amp;#x22;;import remarkParse from &amp;#x22;remark-parse&amp;#x22;;import remarkRehype from &amp;#x22;remark-rehype&amp;#x22;;import rehypeStringify from &amp;#x22;rehype-stringify&amp;#x22;;import rehypeExpressiveCode from &amp;#x22;rehype-expressive-code&amp;#x22;;export default function (eleventyConfig) {  // other config...  const codeBackground = &amp;#x60;var(--pico-code-background-color)&amp;#x60;;  const codeBackgroundLighter = &amp;#x22;var(--pico-background-color)&amp;#x22;;  const codeBorder = &amp;#x22;var(--pico-blockquote-border-color)&amp;#x22;;  eleventyConfig.setLibrary(&amp;#x22;md&amp;#x22;, {    render: async (content, pageContext) =&gt; {      return await unified()        .use(remarkParse)        .use(remarkRehype)        .use(rehypeExpressiveCode, {          themes: [&amp;#x22;dark-plus&amp;#x22;],          styleOverrides: {            codeBackground: codeBackground,            borderColor: codeBorder,            frames: {              editorActiveTabBackground: codeBackground,              editorTabBarBackground: codeBackgroundLighter,              terminalBackground: codeBackground,              terminalTitlebarBackground: codeBackgroundLighter,            },          },          shiki: { transformers: [transformerColorizedBrackets()] },        })        .use(rehypeStringify)        .data({          pageContext,          eleventyConfig,        })        .process(content);    },  });}&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;PS: all the code blocks in this article are highlighted with the above config. You can really see the colored brackets in the last couple 🌈&lt;/p&gt;</description>
      <pubDate>Sun, 26 Jan 2025 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/shiki-colored-brackets/</guid>
    </item>
    <item>
      <title>One Year of StellarMaps</title>
      <link>https://oatmeal.gg/blog/one-year-of-stellarmaps/</link>
      <description>&lt;p&gt;Last August, I started working on a program to draw maps of Stellaris saves. It started as just an experiment, a way to play with some technologies. Maybe a few weeks or a couple months. Well, here I am one year and thousands of lines of code later, still working on it, and it&#39;s been my main (but not only) non-work project for the duration.&lt;/p&gt;
&lt;h2&gt;What is StellarMaps?&lt;/h2&gt;
&lt;p&gt;StellarMaps is a program makes stylized and customizable maps from the &lt;a href=&quot;https://www.paradoxinteractive.com/games/stellaris/about&quot;&gt;sci-fi strategy game Stellaris&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are some existing programs with this capability, such as &lt;a href=&quot;https://randomcomputeruser.github.io/stellaris/stellaris-map-generator/index.html&quot;&gt;RandomComputerUser&#39;s Stellaris Map Generator&lt;/a&gt;, &lt;a href=&quot;https://stellaris-galaxy-map.website.yandexcloud.net/&quot;&gt;myaut&#39;s Stellaris Galaxy Map&lt;/a&gt;, and &lt;a href=&quot;https://steamcommunity.com/sharedfiles/filedetails/?id=1466534202&quot;&gt;blubblubblobb&#39;s Stellaris Dashboard&lt;/a&gt;. However, none of these are as customizable as I would like, and are missing various feature&#39;s such as displaying country emblems. I decided to make yet another, partly to address those issues and partly because making maps is simply fun.&lt;/p&gt;
&lt;h2&gt;The Progress So Far&lt;/h2&gt;
&lt;p&gt;StellarMaps has come far, from the first screenshot I posted to today:&lt;/p&gt;
&lt;p&gt;This year, I released 11 feature updates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;0.1: borders, stars, and hyperlanes&lt;/li&gt;
&lt;li&gt;0.2: country names and emblems&lt;/li&gt;
&lt;li&gt;0.3: sector borders, capital/populated solar system icons&lt;/li&gt;
&lt;li&gt;0.4: unions mode, terra incognita, circular borders style&lt;/li&gt;
&lt;li&gt;0.5: PNG export&lt;/li&gt;
&lt;li&gt;0.6: mod support&lt;/li&gt;
&lt;li&gt;0.7: savings styles, lots of customization options, &quot;metro&quot; style&lt;/li&gt;
&lt;li&gt;0.8: wormhole/gateway icons and paths&lt;/li&gt;
&lt;li&gt;0.9: solar system tooltips, big under-the-hood rendering changes&lt;/li&gt;
&lt;li&gt;0.10: starscape graphics, rewritten save parser&lt;/li&gt;
&lt;li&gt;0.11: system labels, localization support&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The Future&lt;/h2&gt;
&lt;p&gt;I&#39;m currently working on 0.12, the main feature of which is map modes and legends. &quot;Map modes&quot; are options for displaying data on the map, besides borders and locations. For example, coloring countries based on their relation with the player country. Stellaris has a set of map modes in-game. They are moddable, but quite limited. Critically, they can only change the colors of country borders, and cannot display data on anything more granular, like solar systems. With StellarMaps, I can explore map modes that are impossible in-game, such as this WIP population map mode:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/one-year-of-stellarmaps/Ln5VJ_E8gO-637.webp&quot; alt=&quot;A partial map of a galaxy, with colored circles indicating centers of population&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;637&quot; height=&quot;628&quot;&gt;&lt;/p&gt;
&lt;p&gt;After 0.12, I plan to add the ability to generate timelapses of the galaxy. Maps are cool, timelapses are cool, and together they&#39;re amazing. Even before the 0.1 release, I posted about how someday I&#39;d love to generate timelapses, so that&#39;s definitely been a long-term goal of the project that&#39;s gotten pushed back multiple times. I&#39;m committing to 0.13. For real this time.&lt;/p&gt;
&lt;p&gt;Beyond that, things get hazier. This could be a never-ending project. There will always be more data that could be displayed, or new ways of displaying that data, or just options for styles. I will definitely implement some of that, but there&#39;s also larger features I could explore. Most intriguing to me at the moment, is the possibility of expanding StellarMaps beyond Stellaris. Several people have expressed interest in using StellarMaps to create sci-fi maps for their fiction and world-building projects. That would be a large undertaking, but could bring StellarMaps to a whole new audience.&lt;/p&gt;
&lt;h2&gt;Personal Reflection&lt;/h2&gt;
&lt;p&gt;Spending a year (or multiple years?) working on a tool (or toy?) for someone else&#39;s game is not something that was ever a goal of mine. From a certain perspective, this project hurts my goals: I aspire to make games (as suggested by username), and working fulltime as a software developer, my free time and mental capacity is limited. I can only substantially make progress on one non-work project at a time. Working on StellarMaps has a large opportunity cost.&lt;/p&gt;
&lt;p&gt;However, I need to ask myself why I make games? In rough priority:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;personal creative fulfillment&lt;/li&gt;
&lt;li&gt;make something others enjoy&lt;/li&gt;
&lt;li&gt;hone my software development skills&lt;/li&gt;
&lt;li&gt;maybe some additional income?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;StellarMaps actually fulfills all of these:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it is creatively engaging work&lt;/li&gt;
&lt;li&gt;others are using it, and bonus, they are using it as a tool in their own creative endeavors&lt;/li&gt;
&lt;li&gt;it is a technically challenging project&lt;/li&gt;
&lt;li&gt;no money yet, but I&#39;ve had multiple people ask about a Patreon&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So StellarMaps will remain my main project at least through 0.13 (timelapses), and perhaps beyond. We&#39;ll see what the next year brings.&lt;/p&gt;</description>
      <pubDate>Wed, 28 Aug 2024 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/one-year-of-stellarmaps/</guid>
    </item>
    <item>
      <title>Long Time No Blog</title>
      <link>https://oatmeal.gg/blog/long-time-no-blog/</link>
      <description>&lt;p&gt;This blog was originally my dev log for Reflector: Laser Defense. I stopped working on that project, but I kept working on other things!&lt;/p&gt;
&lt;p&gt;So, what have I been up to the last 2 and half years?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;wrote several popular mods for Stellaris&lt;/li&gt;
&lt;li&gt;made an app to draw stylized maps from Stellaris saves&lt;/li&gt;
&lt;li&gt;started contributing to and then maintaining the Stellaris Dashboard&lt;/li&gt;
&lt;li&gt;changed jobs a few times&lt;/li&gt;
&lt;li&gt;started and abandoned other smaller projects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I guess mostly Stellaris!&lt;/p&gt;
&lt;p&gt;This blog will no longer be about only Reflector. I&#39;ll post about whatever I&#39;m working on. In the near-term, probably more Stellaris.&lt;/p&gt;</description>
      <pubDate>Sun, 28 Jul 2024 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/long-time-no-blog/</guid>
    </item>
    <item>
      <title>Reflector: Laser Defense Alpha 3.0.1 Release</title>
      <link>https://oatmeal.gg/blog/reflector-release-3.0.1/</link>
      <description>&lt;p&gt;This release contains a collection of bug fixes and UI tweaks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;NEW: Click to move setting&lt;/li&gt;
&lt;li&gt;NEW: Warn player that there are no saves or undo in private browsing&lt;/li&gt;
&lt;li&gt;MOD: F10 is used to open menu instead of Esc&lt;/li&gt;
&lt;li&gt;MOD: Esc can be used in addition to Q as &quot;Back&quot; keybinding&lt;/li&gt;
&lt;li&gt;MOD: Q/Esc only clears map cursor if using keyboard cursor controls&lt;/li&gt;
&lt;li&gt;MOD: Q/Esc will open main menu if it is not used for anything else&lt;/li&gt;
&lt;li&gt;MOD: Split Misc category into Housing and Infrastructure&lt;/li&gt;
&lt;li&gt;MOD: Added new playtesters to credits&lt;/li&gt;
&lt;li&gt;FIX: Outdated text in Residence tutorial&lt;/li&gt;
&lt;li&gt;FIX: Colonists not assigned to tents&lt;/li&gt;
&lt;li&gt;FIX: Colonists not reassigning residence during day&lt;/li&gt;
&lt;li&gt;FIX: Game crashes in private browsing mode&lt;/li&gt;
&lt;li&gt;FIX: blueprint conditions checked previous position instead of current&lt;/li&gt;
&lt;li&gt;FIX: sliders for music/sfx volume are empty white boxes&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Fri, 28 Jan 2022 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-release-3.0.1/</guid>
    </item>
    <item>
      <title>Reflector: Laser Defense Alpha 3 Release</title>
      <link>https://oatmeal.gg/blog/reflector-release-3.0.0/</link>
      <description>&lt;p&gt;A year in the making, Alpha 3 is here! Play now on itch.io!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-release-3.0.0/6TnLDEssMz-509.webp&quot; alt=&quot;gif&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;509&quot; height=&quot;331&quot;&gt;&lt;/p&gt;
&lt;p&gt;Alpha 3 is released and it&#39;s a big one! Almost everything has been expanded or reworked. Here&#39;s some highlights:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enemy Variety&lt;/strong&gt;: three new enemies each with new mechanics and challenges&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Map Variety&lt;/strong&gt;: 5 new map types, from open plains, to rugged badlands&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New Buildings&lt;/strong&gt;: the player gets new toys too! Roads, absorbers, shield generators, and more!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Overhauled Economy&lt;/strong&gt;: the economy has been rebalanced and many buildings reworked. Farms take a full day to produce food, so make sure you defend them overnight!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Music and Sound Effects&lt;/strong&gt;: the world isn&#39;t so quiet anymore&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And loads of other changes big and small. A year in the making, this update really fleshes out the game.&lt;/p&gt;</description>
      <pubDate>Thu, 20 Jan 2022 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-release-3.0.0/</guid>
    </item>
    <item>
      <title>Devlog November 3, 2021</title>
      <link>https://oatmeal.gg/blog/devlog-2021-11-03/</link>
      <description>&lt;p&gt;Lots of progress the past 2 months! All the new content for Alpha 3 is done, and now I&#39;m working on the long tail of balance and polish. Here&#39;s a quick summary of whats new:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Absorbers&lt;/strong&gt;: A new building that can &quot;store&quot; a laser shot for later&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shield Generators&lt;/strong&gt;: Another new building that uses a lot of power to protect your buildings, but it also blocks your own lasers!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improved Laser Graphics&lt;/strong&gt;: Lasers glow and pulse while aiming, and flash when you shoot&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Less Random Enemy Waves&lt;/strong&gt;: This especially effects the early days, which could be swing wildly with the RNG&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Visible Farm Growth&lt;/strong&gt;: This helps you see your progress, but also comes with a small gameplay change: when enemies attack farms, they destroy the growth but leave the field itself intact&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Move Fast on Roads&lt;/strong&gt;: The player character now benefits from roads! Previously only your colonists did&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Buildable Tents&lt;/strong&gt;: You now have control over tent placement. No more will your plans be ruined when a colonist decides to pitch a tent in a critical location!&lt;/li&gt;
&lt;li&gt;And lots of other bug fixes and usability improvements!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Take a look at the new graphics (and the fast roads):
&lt;img src=&quot;https://oatmeal.gg/blog/devlog-2021-11-03/vvFfHxoxiP-600.webp&quot; alt=&quot;laser&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;400&quot;&gt;&lt;/p&gt;
&lt;p&gt;The release of Alpha 3 is in sight, but I still have lots of balance and usability improvements to do. Plan is to release around the New Year!&lt;/p&gt;</description>
      <pubDate>Wed, 03 Nov 2021 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/devlog-2021-11-03/</guid>
    </item>
    <item>
      <title>Devlog September 2, 2021</title>
      <link>https://oatmeal.gg/blog/devlog-2021-09-02/</link>
      <description>&lt;p&gt;This month mostly got derailed by a home search (spoiler alert: next month will be derailed by moving), but I still got a decent amount done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Map Variety&lt;/strong&gt;: there are now 6 types of maps: standard, marsh, badlands, plains, lakes, and mesa! For now, one of those is selected randomly, but for release there will be a menu to choose your map type. Marsh and badlands in particular should make for some challenging base building.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Longer-lasting Reflectors&lt;/strong&gt;: New players are often confused by reflector/projector range. To help make that clearer, instead of immediately disappearing, reflectors that are out of range will stay for one turn and flash.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stronger Walls&lt;/strong&gt;: Slight buff to walls, which can now take 3 hits instead of 2.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Big Updates Under the Covers&lt;/strong&gt;: Updated basically all of the build tools and 3rd party libraries, for a smoother development workflow. The optimized builds are broken currently, so I&#39;ll a little more to do here before release.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&#39;s a screenshot of the maps:
&lt;img src=&quot;https://oatmeal.gg/blog/devlog-2021-09-02/gyqp8wOE39-920.webp&quot; alt=&quot;maps&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;613&quot;&gt;&lt;/p&gt;
&lt;p&gt;And a gif of the reflectors:
&lt;img src=&quot;https://oatmeal.gg/blog/devlog-2021-09-02/yit2J8tLOc-313.webp&quot; alt=&quot;reflector&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;313&quot; height=&quot;216&quot;&gt;&lt;/p&gt;
&lt;p&gt;I&#39;m moving next month, so I don&#39;t expect to get a whole lot done. Next up are the absorber and shield generator buildings, which will finish off the new content for Alpha 3. Hopefully I can get those done. Then it&#39;s a lot of balance, tweaks, and UI.&lt;/p&gt;</description>
      <pubDate>Thu, 02 Sep 2021 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/devlog-2021-09-02/</guid>
    </item>
    <item>
      <title>Devlog August 3, 2021</title>
      <link>https://oatmeal.gg/blog/devlog-2021-08-03/</link>
      <description>&lt;p&gt;This month I worked on new content for the player! There&#39;s more of that to come, but here&#39;s what&#39;s coming to Alpha 3 so far:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Roads&lt;/strong&gt;: colonists move twice as fast! Less time going to work, more time working!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Warehouse and Batteries&lt;/strong&gt;: You now need places to store your resources. You need to be careful with placement, batteries are explosive!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Farm Overhaul&lt;/strong&gt;: Instead of simply providing food while being worked, colonists now need to work on the farm for a long time, then produce a bunch of food all at once. Planning and defense is more important than ever!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reactor Overhaul&lt;/strong&gt;: Reactors now produce a lot of power, and don&#39;t require colonists to work in them, but there&#39;s a catch. If you have excess power and no batteries to store it, the reactors will overheat and explode!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rebalanced Economy&lt;/strong&gt;: All workable buildings now follow the same model as the farm -- colonists work for several turns then produce some resources. The resource numbers are generally smaller than before, but easier for me to balance.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&#39;s a little screenshot of a colony with some of the new buildings:
&lt;img src=&quot;https://oatmeal.gg/blog/devlog-2021-08-03/QU4CA_DiCg-768.webp&quot; alt=&quot;screenshot&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next month I&#39;m hoping to finish up the new content for Alpha 3. A few new defensive buildings, new map generation options, revamped enemy spawning. After that, there will a long tail of balance, graphics, UX, and tutorial work, likely lasting a couple more months. I guess that puts Alpha 3 out December/January.&lt;/p&gt;</description>
      <pubDate>Tue, 03 Aug 2021 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/devlog-2021-08-03/</guid>
    </item>
    <item>
      <title>Devlog July 2, 2021</title>
      <link>https://oatmeal.gg/blog/devlog-2021-07-02/</link>
      <description>&lt;p&gt;Lots of progress towards Alpha 3 this month. I implemented all of the new enemies, bringing the total from 1 to 5:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Soldier: basic enemy that is already in the game&lt;/li&gt;
&lt;li&gt;Beetle: armored enemy that blocks 1 laser, then turns into soldier&lt;/li&gt;
&lt;li&gt;Flyer: winged enemy that can fly over water&lt;/li&gt;
&lt;li&gt;Burrower: digging enemy that evades your lasers until it&#39;s ready to attack&lt;/li&gt;
&lt;li&gt;Volatile: explosive enemy that damages everything adjacent when it dies&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/devlog-2021-07-02/15efCb4roU-530.webp&quot; alt=&quot;New Enemies&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;530&quot; height=&quot;528&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next, I rewrote the AI. It now chooses it&#39;s targets more intelligently, paths to them better, and coordinates with other enemies. These improvements will also enable some interesting new defensive buildings for the player. Additionally, there&#39;s now an indication of the AI&#39;s next move. Players could see this before by waiting a turn, remembering where the AI went, then undoing that turn. That&#39;s annoying, but could be optimal in some situations, so I decided to make that an actual feature:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/devlog-2021-07-02/XDRMmwYOrP-530.webp&quot; alt=&quot;Movement Indicators&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;530&quot; height=&quot;528&quot;&gt;&lt;/p&gt;
&lt;p&gt;Next month, I&#39;m moving on to new buildings for the player. Roads, warehouses, batteries, decoys, shield generators... and reworks of farms and generators. Lots of new toys for the player!&lt;/p&gt;</description>
      <pubDate>Fri, 02 Jul 2021 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/devlog-2021-07-02/</guid>
    </item>
    <item>
      <title>Devlog June 2, 2021</title>
      <link>https://oatmeal.gg/blog/devlog-2021-06-02/</link>
      <description>&lt;h3&gt;Where I&#39;ve Been&lt;/h3&gt;
&lt;p&gt;It&#39;s been a while since I posted here. As planned, I did not work on Reflector much in March. Most of the month was spent preparing for the 7 Day Roguelike game jam, making the game, and then working on a couple bugfix/balance updates for the game. Not as planned, I hardly did any game development during April and May. I needed a bit of a break after the jam, and momentum kept the break going longer than planned. Trying to work on both Reflector and updates for my 7DRL game at the same time did not help. I&#39;ve decided to focus on Reflector until I get the next major update out.&lt;/p&gt;
&lt;h3&gt;Reflector&lt;/h3&gt;
&lt;p&gt;So, what&#39;s the status of Reflector? I have managed some progress over the past few months. Sound effects and music are now fully implemented. I&#39;ll continue tweaking volumes and whatnot, but all of the audio is in game and playing when it&#39;s supposed to! Next up, I&#39;ll be doing a few graphical improvements and then starting to work on the new enemies and buildings for alpha 3.&lt;/p&gt;
&lt;h3&gt;Wyrm&#39;s Wrath&lt;/h3&gt;
&lt;p&gt;This is the game I made for 7DRL 2021, which you can &lt;a href=&quot;https://oatmealproblem.itch.io/wyrms-wrath&quot;&gt;play here on itch.io&lt;/a&gt;. Play as primordial beast. Eat your enemies to harness the powers of Mushroom, Crystal, and Slime. Kill the King and get your revenge.&lt;/p&gt;
&lt;p&gt;I have some pretty major changes planned for this, but it&#39;s on hold for now. After releasing Reflector Alpha 3 and following up with any needed patches, I&#39;ll return to work on the 2.0 update for this.&lt;/p&gt;</description>
      <pubDate>Wed, 02 Jun 2021 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/devlog-2021-06-02/</guid>
    </item>
    <item>
      <title>Reflector Monthly Update - February 2021</title>
      <link>https://oatmeal.gg/blog/reflector-02-2021/</link>
      <description>&lt;p&gt;Behind the scenes refactoring continues, but I also made some improvements to the graphics. Here&#39;s a gif demonstrating many of the improvements:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-02-2021/okvZERwgVf-920.webp&quot; alt=&quot;Graphical Improvements&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;577&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The player, enemies, and colonists now slide smoothly between tiles instead of teleporting from one spot to the next.&lt;/li&gt;
&lt;li&gt;Enemies &quot;bump&quot; towards the thing they attack&lt;/li&gt;
&lt;li&gt;There&#39;s a destruction animation. Currently it&#39;s an explosion, but that will likely change to something more like a dust cloud, as explodable things is a planned mechanic for Alpha 3.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These last 3 are not in the gif:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Audio! I hear most games include this. Reflector now has music and some placeholder sfx.&lt;/li&gt;
&lt;li&gt;The building preview in the build menu now fully renders the buildings, instead of a single-color silhouette.&lt;/li&gt;
&lt;li&gt;Some buildings can now be built on top of others, without first needing to deconstruct. For example, advanced splitter on top of a splitter.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;March is likely not to be especially productive, as this first week will be spent preparing for the 7DRL game jam, the second week actually doing the jam, and then I&#39;ll possibly follow-up with a bug fix release for the 7DRL. April should see a start on new mechanics and content for Alpha 3.&lt;/p&gt;</description>
      <pubDate>Wed, 03 Mar 2021 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-02-2021/</guid>
    </item>
    <item>
      <title>Reflector Monthly Update - January 2021</title>
      <link>https://oatmeal.gg/blog/reflector-01-2021/</link>
      <description>&lt;p&gt;I spent the first part of this month planning, building, and testing the new interactive tutorial. That has been released along with all the other changes from the past 3 months, so rather than talking about it at length, I&#39;ll just let you go play it over at &lt;a href=&quot;https://oatmealproblem.itch.io/reflector&quot;&gt;itch.io&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;After the release, I took a bit of a brake for relaxation and so I wouldn&#39;t be in the middle of anything if any major bugs came up. Looks like the current release is pretty stable, so I&#39;ve started working on Alpha 3, which is focused on combat. To start off though, I&#39;m cleaning up some older parts of the code.&lt;/p&gt;
&lt;p&gt;First up was the building code. I couldn&#39;t resist making a UI improvement that the new and improved code made possible: the inspector now tells you specifically why you cannot build in invalid locations:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-01-2021/nzwcXjswz3-920.webp&quot; alt=&quot;Specific invalid build reasons&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;577&quot;&gt;&lt;/p&gt;
&lt;p&gt;This next month will probably be more code cleanup and small tweaks like the above, and I likely won&#39;t start working on the heart of Alpha 3 until March.&lt;/p&gt;
&lt;p&gt;If you want to read more about long term plans, as well as review of the year, &lt;a href=&quot;https://www.reddit.com/r/roguelikedev/comments/l2q1je/2021_in_roguelikedev_reflector_laser_defense/&quot;&gt;I wrote a post&lt;/a&gt; for the 2021 in RoguelikeDev event over on r/roguelikedev.&lt;/p&gt;</description>
      <pubDate>Mon, 01 Feb 2021 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-01-2021/</guid>
    </item>
    <item>
      <title>Reflector: Laser Defense Alpha 2.1 Release</title>
      <link>https://oatmeal.gg/blog/reflector-release-2.1.0/</link>
      <description>&lt;p&gt;Four months in the making, Alpha 2.1 is finally here! Go play it at itch.io!&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-release-2.1.0/3_64Ahg7Lf-920.webp&quot; alt=&quot;Tutorial GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;600&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here&#39;s what it all includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;An interactive tutorial to teach the basics&lt;/li&gt;
&lt;li&gt;Full keyboard support. Play with only keyboard, only mouse, or somewhere in between&lt;/li&gt;
&lt;li&gt;Big rebalance of buildings and costs&lt;/li&gt;
&lt;li&gt;Many, many usability improvements&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reflector: Laser Defense has never been more accessible, so if you had trouble before, give it another go!&lt;/p&gt;</description>
      <pubDate>Fri, 22 Jan 2021 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-release-2.1.0/</guid>
    </item>
    <item>
      <title>Reflector Monthly Update - December 2020</title>
      <link>https://oatmeal.gg/blog/reflector-12-2020/</link>
      <description>&lt;p&gt;This month, I finished everything I want for the Alpha 2.1 release, except I&#39;ve decided to add one more thing: an interactive tutorial. I&#39;m not currently collecting any metrics, but from the feedback I have, it seems like many potential players are bouncing off because of the lack of a tutorial. This has been on my to-do list though originally just in the &quot;before I call this game complete&quot; category. It has gradually become higher and higher priority. First, getting schedules for Alpha 4, then Alpha 3, and now finally Alpha 2.1.&lt;/p&gt;
&lt;p&gt;So, what will this tutorial actually look like? I&#39;m still figuring out the details, but the plan is for it to take the in-game assistant form. So instead of a separate tutorial level, you will start an actual game and various triggers will tips about controls and mechanics, which can then be manually dismissed or automatically dismissed by player actions. This style of tutorial can be seen in Frostpunk, RimWorld, Stellaris, and I&#39;m sure many other games. This will be more work up front, but should require less maintenance than static tutorial levels or recorded videos.&lt;/p&gt;
&lt;p&gt;With that said, Alpha 2.1 is probably a few weeks out. As always, if you want to try the bleeding edge version, you can do so at https://reflector-unstable.netlify.app. Feedback is much appreciated!&lt;/p&gt;
&lt;p&gt;Enough talk about the future -- what did I get done this past month? Lots!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Contextual quick actions.&lt;/strong&gt; Clicking on the map used to just cycle between reflectors, and anything else required right-clicking. Now it is contextual based on the contents of the tile and the game state: build, move, cancel move, place/rotate/remove reflector, disable/enable jobs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Click to move.&lt;/strong&gt; This is something multiple playtesters tried to do. Initially, I didn&#39;t plan on implementing this, because clicking to place reflectors is very convenient, but the contextual quick action framework provided a solution: while aiming, click will cycle reflectors, otherwise clicking will move you to the location. Moving across the entire map can be deadly though, as I discovered while testing this feature, so if any enemies are present you will only move 1 space.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-12-2020/OZn1ATptLH-768.webp&quot; alt=&quot;Quick actions and click-to-move&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Building warnings.&lt;/strong&gt; There are some things you&#39;re allowed to do, but probably shouldn&#39;t. Now when building, warning can be shown if you might want to reconsider a certain position. This is currently only used for buildings that would block windmills, but definitely could be used for other things in the future.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-12-2020/-bu03nMNVE-639.webp&quot; alt=&quot;Windmill warning&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;639&quot; height=&quot;400&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Keyboard controls for job priorities.&lt;/strong&gt; This was the last piece of UI that was mouse-only. Now everything can be done with keyboard only (or mouse only) for those who prefer or require it.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-12-2020/qRD5vFjMWX-263.webp&quot; alt=&quot;Job priority keyboard controls&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;263&quot; height=&quot;213&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Misc actions in the bottom menu.&lt;/strong&gt; Clear reflectors, undo, wait, and dismiss notifications are now all in the bottom right. Before they were scattered about in various places (except dismiss notifications, which didn&#39;t exist before)&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-12-2020/ocKWlVm4UE-296.webp&quot; alt=&quot;Miscellaneous action bar&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;296&quot; height=&quot;140&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Show laser on player tile.&lt;/strong&gt; Before the laser you&#39;re aiming didn&#39;t start until the tile next to the player, which could be confusing when standing next to a mountain which blocks all lasers.&lt;/p&gt;
&lt;p&gt;Before: &lt;img src=&quot;https://oatmeal.gg/blog/reflector-12-2020/uKimapqKya-120.webp&quot; alt=&quot;laser before&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;120&quot; height=&quot;120&quot;&gt;&lt;/p&gt;
&lt;p&gt;After: &lt;img src=&quot;https://oatmeal.gg/blog/reflector-12-2020/yvcTOTVgl5-120.webp&quot; alt=&quot;laser after&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;120&quot; height=&quot;120&quot;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Big Economy Rebalance.&lt;/strong&gt; Most buildings are more expensive to build and require more energy to maintain. Machinery is much more expensive. Windmills and reactors provide more energy.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;No more time.&lt;/strong&gt; Each turn represents 15 minutes of in-game time, and the status showed the current time of day. This abstraction seemed to cause some confusion, with sometimes players not realizing at first the game is turn-based. Now instead it just showed the current turn of the day/night. So &quot;Day 1, Turn 1&quot; instead of &quot;Day 1, 6:00am&quot;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Lots and lots of smaller tweaks and fixes.&lt;/strong&gt; This &quot;small&quot; release has taken longer than planned, but will be worth it! There&#39;s no big gameplay changes, but lots of polish to the UI that should be a big help for new and existing players alike!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Fri, 01 Jan 2021 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-12-2020/</guid>
    </item>
    <item>
      <title>Reflector Monthly Update - November 2020</title>
      <link>https://oatmeal.gg/blog/reflector-11-2020/</link>
      <description>&lt;p&gt;For alpha 2, the game was mostly playable with only keyboard, but there were a few menus and miscellaneous controls that were mouse only. Much of this month was spent addressing those last few mouse-only UIs. I ran into some limitations with the hotkey library I was using, and after trying a couple others, decided to write my own. That was a fair bit of work, but I&#39;m happy with the result. Now everything except changing job priorities can be done via keyboard. I need a bit of break from working on hotkeys, but I&#39;ll address job priorities before the release of 2.1.&lt;/p&gt;
&lt;p&gt;While working on the hotkeys, I also made some updates to the contextual action menu (right-clicking on the map) and the build menu. They now both make use the library I&#39;m using for tooltips, which helps simplify some of my code and also gives a more consistent look and feel. Here&#39;s the results:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-11-2020/T1qAPRHd5U-768.webp&quot; alt=&quot;New Build Menu&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;800&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-11-2020/ba5mal_mad-768.webp&quot; alt=&quot;New Context Menu&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot;&gt;&lt;/p&gt;
&lt;p&gt;I was looking at a late November or early December release, but the keyboard work took a bit longer than expected (especially because it wasn&#39;t exciting work, so it drove my productivity down). Now I&#39;m looking at getting something out for the New Year. I&#39;ll have a decent chunk of time off from my day job at the end of the year, so I should be able to get good amount done.&lt;/p&gt;</description>
      <pubDate>Mon, 07 Dec 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-11-2020/</guid>
    </item>
    <item>
      <title>Reflector Monthly Update - October 2020</title>
      <link>https://oatmeal.gg/blog/reflector-10-2020/</link>
      <description>&lt;p&gt;Short update this time around. As planned, I&#39;ve slowed down the pace of development a bit after the release of Alpha 2. I&#39;m working on incorporating feedback, refactoring some messy code, improving performance, and adding full keyboard support.&lt;/p&gt;
&lt;p&gt;The only visual change to share this month is some changes to make enemies easier to see. Some players didn&#39;t notice enemies approaching until it was too late. To address this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enemies are now a brighter color&lt;/li&gt;
&lt;li&gt;Farms, fertile land, and ore are now duller colors&lt;/li&gt;
&lt;li&gt;Enemies now have a slightly animated sprite&lt;/li&gt;
&lt;li&gt;Enemies flash when they first enter the screen&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Here&#39;s the result:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-10-2020/wFM4S8_lW5-480.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;480&quot; height=&quot;480&quot;&gt;&lt;/p&gt;
&lt;p&gt;November I&#39;ll continue working on some UX and balance changes for 2.1, which I currently plan to release late November or early December. That release most likely will not include an interactive tutorial, which will instead come in 2.2 or 3.0.&lt;/p&gt;</description>
      <pubDate>Sat, 07 Nov 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-10-2020/</guid>
    </item>
    <item>
      <title>Reflector Monthly Update - September 2020</title>
      <link>https://oatmeal.gg/blog/reflector-09-2020/</link>
      <description>&lt;p&gt;&lt;a href=&quot;https://oatmealproblem.itch.io/reflector&quot;&gt;Alpha 2 is out!&lt;/a&gt; September was jam packed with playtesting and lots of usability tweaks. But you can check those out for yourself.&lt;/p&gt;
&lt;h1&gt;What&#39;s next?&lt;/h1&gt;
&lt;p&gt;First will be at least one, potentially multiple, minor releases focused on more usability and performance. These are some of the priorities for that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Full keyboard controls.&lt;/strong&gt; Menus, job priorities, and zoom don&#39;t have keyboard controls yet.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Make enemies easier to see.&lt;/strong&gt; Some players haven&#39;t seen enemies approaching until too late. That&#39;s not supposed to be the hard part.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Performance improvements.&lt;/strong&gt; Late game can get a little sluggish between turns. Eventually, I might rewrite in the core game code in Rust/wasm, but in the meantime there&#39;s optimizations I can make in JavaScript.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Revisit job assignment and priorities.&lt;/strong&gt; Job priorities confuses many players, but is important for managing your resources. I have a few ideas for improving this.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Interactive tutorial.&lt;/strong&gt; I&#39;ve had lots of requests for this. This might get pushed into Alpha 3 instead of minor 2.x release.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code cleanup.&lt;/strong&gt; It&#39;s time to purge bad code before embarking on another major release.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That should keep me busy for a while, especially since I&#39;m going to slow back down to a sustainable pace. But, I have a pretty good idea of what will be in the Alpha 3.&lt;/p&gt;
&lt;h1&gt;Alpha 3&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;More enemy diversity.&lt;/strong&gt; 4 new enemy types planned, but possibly more.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;More defensive buildings.&lt;/strong&gt; It&#39;s only fair if the player gets some more tricks too.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Gameplay experiments.&lt;/strong&gt; I&#39;ll be trying these out, but I&#39;ll have to see how they play.
&lt;ul&gt;
&lt;li&gt;Place blueprints for colonists to build.&lt;/li&gt;
&lt;li&gt;More varied maps. Maps with lots of lakes. Maps with lots of mountains. Etc.&lt;/li&gt;
&lt;li&gt;Building deconstruction. Send colonists to deconstruct to get resources back.&lt;/li&gt;
&lt;li&gt;Building rubble. Quickly rebuild destroyed buildings, or scavenge some resources.&lt;/li&gt;
&lt;li&gt;Experiment with defensive building power management. Automatically turn off defensive buildings during the day. Other experiments.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I have tentative plants for Alpha 4 and 5 as well, but those will probably change by the time I get around to them. In general I&#39;ll be trying to keep each Alpha a little smaller from here on out, so releases are 3-6 months apart instead of almost a full year.&lt;/p&gt;</description>
      <pubDate>Sun, 04 Oct 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-09-2020/</guid>
    </item>
    <item>
      <title>Reflector: Laser Defense Alpha 2 Release</title>
      <link>https://oatmeal.gg/blog/reflector-release-2.0.0/</link>
      <description>&lt;p&gt;Alpha 2 is finally released! Go play it at itch.io!&lt;/p&gt;
&lt;p&gt;Here&#39;s what it all includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Much expanded base building and management
&lt;ul&gt;
&lt;li&gt;Colonists now go to work during the day&lt;/li&gt;
&lt;li&gt;Grow food for to feed colonists&lt;/li&gt;
&lt;li&gt;Produce machinery from metal to build advanced buildings&lt;/li&gt;
&lt;li&gt;Generate power, otherwise your defensive buildings won&#39;t work&lt;/li&gt;
&lt;li&gt;Many new buildings&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Simplified but more powerful lasers&lt;/li&gt;
&lt;li&gt;Overhaul to the graphics&lt;/li&gt;
&lt;li&gt;Completely new UI, with full mouse controls&lt;/li&gt;
&lt;li&gt;Many smaller changes&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Thu, 01 Oct 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-release-2.0.0/</guid>
    </item>
    <item>
      <title>Reflector Monthly Update - August 2020</title>
      <link>https://oatmeal.gg/blog/reflector-08-2020/</link>
      <description>&lt;p&gt;This was my most productive month in a while! Alpha 2 really feels like it&#39;s shaping up.&lt;/p&gt;
&lt;p&gt;The most exciting changes this month:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Windmills now spin when they&#39;re working.
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-08-2020/b2GSGLFcSW-289.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;289&quot; height=&quot;257&quot;&gt;&lt;/li&gt;
&lt;li&gt;The map background color now changes with night and day. Day and night is very important in Reflector. Colonists work during the day. Enemies attack at night. For something so central to the game, it wasn&#39;t very visible until now.
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-08-2020/HFYH0vqewB-920.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;748&quot;&gt;&lt;/li&gt;
&lt;li&gt;Single turn undo. Everything in Reflector dies in a single hit, so a single mistake can mean game over. Combat is fully deterministic (no dice rolls or the like), so an undo system can&#39;t be abused like it could in some other games. If you lose, the undo button will be displayed in the game over pop up, but it can also be used at other times via a keyboard shortcut or the (unimplemented) menu in the top right.
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-08-2020/oDCavobN4l-920.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;748&quot;&gt;&lt;/li&gt;
&lt;li&gt;Laser must recharge for a turn after firing. In Alpha 1, lasers had strength, and each time they hit something or were split, they lost one strength, until they reached zero and stopped. This mechanic seemed to cause some confusion, so a while back I changed it so lasers have infinite strength, but that&#39;s a little too strong now. Rather than reintroducing limited strength (it just feels better to fling lasers all the way across the map), I added a one turn cooldown between shooting. The UI for this can be seen in the gif above.&lt;/li&gt;
&lt;li&gt;Buildings that can be inactive or active now toggle between a bright gray or dark gray.
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-08-2020/6YdMdOG9Ff-768.webp&quot; alt=&quot;PNG&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Less flashy, but I also got the following done:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fixed a longstanding bug that caused destroyed things to still be visible and things that do exist to be invisible&lt;/li&gt;
&lt;li&gt;Found a keyboard control scheme that doesn&#39;t annoy me (I can finally playtest for more than 10 minutes at a time, so this is actually the most impactful change)&lt;/li&gt;
&lt;li&gt;Defined all shortcuts and settings in JSON (not exposed to the user yet, but this is the first step towards customizable keyboard shortcuts)&lt;/li&gt;
&lt;li&gt;Thinner outline for highlighted cursor, valid building locations&lt;/li&gt;
&lt;li&gt;Display number of unemployed colonists beneath the jobs&lt;/li&gt;
&lt;li&gt;Display housing capacity along with population&lt;/li&gt;
&lt;li&gt;A variety of less notable bug fixes, balance adjustments, and UI tweaks&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Alpha 2, what&#39;s left?&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;Tooltips everywhere&lt;/li&gt;
&lt;li&gt;Toast messages for a variety of situations&lt;/li&gt;
&lt;li&gt;More information in the inspector&lt;/li&gt;
&lt;li&gt;Menu, with some basic options (new game, view controls, toggle fullscreen)&lt;/li&gt;
&lt;li&gt;Some UI for initial game loading&lt;/li&gt;
&lt;li&gt;Screen to display keyboard shortcuts (won&#39;t be editable for Alpha 2)&lt;/li&gt;
&lt;li&gt;Testing for a variety of screen sizes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Once I get those first three done, I&#39;ll start reaching out to friends and family for some additional playtesting. If nothing major comes up, Alpha 2 should be ready for a late September or early October release. On the other hand, Crusader Kings 3 comes out tomorrow, so September might not be as productive as August.&lt;/p&gt;</description>
      <pubDate>Mon, 31 Aug 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-08-2020/</guid>
    </item>
    <item>
      <title>Reflector Monthly Update - July 2020</title>
      <link>https://oatmeal.gg/blog/reflector-07-2020/</link>
      <description>&lt;p&gt;In July I made many tweaks for balance and UI polish. There will be many more to come for August.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Changed the victory condition from reach population X to survive X days and added a game over dialog with an option to continue playing if you won -- the game is now fully playable from start to finish for the first time since the UI rewrite
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-07-2020/gdgcGqGgu0-324.webp&quot; alt=&quot;PNG&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;324&quot; height=&quot;124&quot;&gt;&lt;/li&gt;
&lt;li&gt;Display messages with toasts
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-07-2020/a3Gm48PM9u-466.webp&quot; alt=&quot;PNG&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;466&quot; height=&quot;228&quot;&gt;&lt;/li&gt;
&lt;li&gt;Change the smoke effect to be more subtle so it doesn&#39;t obscure the tile above too much
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-07-2020/rccTO1NV6x-336.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;336&quot; height=&quot;340&quot;&gt;&lt;/li&gt;
&lt;li&gt;Added a border that shows your reflector placement range
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-07-2020/xDSIc_tFfC-766.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;766&quot; height=&quot;801&quot;&gt;&lt;/li&gt;
&lt;li&gt;Zoom in and out with the mouse wheel
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-07-2020/yWKwfRhAur-766.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;766&quot; height=&quot;801&quot;&gt;&lt;/li&gt;
&lt;li&gt;Added tooltips to the build menu
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-07-2020/e_kEkCTaJu-255.webp&quot; alt=&quot;PNG&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;255&quot; height=&quot;175&quot;&gt;&lt;/li&gt;
&lt;li&gt;Changed the starting setup -- you now start with 3 colonists, a mine, and a farm, instead of a single colonist and a mine&lt;/li&gt;
&lt;li&gt;And a few a bug fixes&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Sun, 02 Aug 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-07-2020/</guid>
    </item>
    <item>
      <title>Reflector Monthly Update - June 2020</title>
      <link>https://oatmeal.gg/blog/reflector-06-2020/</link>
      <description>&lt;p&gt;June was devoted to the four main remaining parts of the new UI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The build menu
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-06-2020/a907xYcV9E-768.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;252&quot;&gt;&lt;/li&gt;
&lt;li&gt;The resources UI
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-06-2020/KuE6MxiQwo-406.webp&quot; alt=&quot;PNG&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;406&quot; height=&quot;156&quot;&gt;&lt;/li&gt;
&lt;li&gt;The jobs UI with drag and drop for changing priority
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-06-2020/iLSV5uAIyW-263.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;263&quot; height=&quot;194&quot;&gt;&lt;/li&gt;
&lt;li&gt;And the status UI
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-06-2020/CSusHm96ey-271.webp&quot; alt=&quot;PNG&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;271&quot; height=&quot;124&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For July, I&#39;ll start alternating between playtesting and the many smaller UI enhancements in my to-do list, as well as a few bug fixes.&lt;/p&gt;</description>
      <pubDate>Fri, 03 Jul 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-06-2020/</guid>
    </item>
    <item>
      <title>Reflector Monthly Update - May 2020</title>
      <link>https://oatmeal.gg/blog/reflector-05-2020/</link>
      <description>&lt;p&gt;May was focused on the big UI redesign for Alpha 2. The main goals of redesign are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Everything should be fully usable with only the mouse or only the keybaord&lt;/li&gt;
&lt;li&gt;All important information should be visible at a glance without needing to &quot;inspect&quot; anything or take any other actions&lt;/li&gt;
&lt;li&gt;Controls and mechanics should be easily discoverable&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I&#39;ve made good progress, especially on the first two points. Here&#39;s a gif demonstrating the changes and below that, a detailed list:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-05-2020/osu5YoZwXQ-920.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;749&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Production buildings emit smoke when they are being worked, indicating how many colonists are working there&lt;/li&gt;
&lt;li&gt;Colonists light up the windows when home, indicating how many are currently in the residence&lt;/li&gt;
&lt;li&gt;The tile that the cursor is hovered over in the map is highlighted&lt;/li&gt;
&lt;li&gt;Right click the map to access a menu of actions available for that tile&lt;/li&gt;
&lt;li&gt;In the side bar, display the contents of the highlighted tile&lt;/li&gt;
&lt;li&gt;In the side bar, display the actions available for the highlighted tile, along with their keyboard shortcuts&lt;/li&gt;
&lt;li&gt;Keyboard controls for changing the highlighted tile (shift + direction moves the highlighted tile)&lt;/li&gt;
&lt;li&gt;Keyboard controls for moving the character (arrows, wasd, or vim keys)&lt;/li&gt;
&lt;li&gt;Keyboard controls for aiming and firing the laser (ctrl + direction to aim, press again to fire)&lt;/li&gt;
&lt;li&gt;Mouse controls in sidebar for aiming and firing the laser&lt;/li&gt;
&lt;li&gt;Click the map to cycle between placing a reflector, rotating it, or removing it. Also works by pressing space or enter&lt;/li&gt;
&lt;li&gt;Lots of miscellaneous changes and refactoring to support all of the above&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first part of June will be dedicated to the remaining major pieces of the new UI: build controls (in progress), the status panel, the resources panel, and the jobs panel. Beyond that, I have a long list of smaller UI enhancements, but at that point I&#39;ll likely start alternating between playtesting/balancing and working on the UI. For alpha 1, testing by both myself and others revealed a lot of UI improvements, so I want to get that started as soon as the new UI is &quot;good enough&quot;.&lt;/p&gt;</description>
      <pubDate>Mon, 01 Jun 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-05-2020/</guid>
    </item>
    <item>
      <title>Update to Devlogs</title>
      <link>https://oatmeal.gg/blog/update-to-devlogs/</link>
      <description>&lt;p&gt;I forgot to post this here. Progress is steady again and I&#39;m working hard on Alpha 2. However, I&#39;ve decided to switch to more substantial monthly updates instead of weekly devlogs. If you want more frequent updates, I occasionally post on &lt;a href=&quot;https://twitter.com/mmakesgames&quot;&gt;Twitter&lt;/a&gt; and &lt;a href=&quot;https://reddit.com/r/roguelikedev&quot;&gt;r/roguelikedev&#39;s Sharing Saturday&lt;/a&gt;. Otherwise, expect an update June 1!&lt;/p&gt;</description>
      <pubDate>Tue, 19 May 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/update-to-devlogs/</guid>
    </item>
    <item>
      <title>Reflector Devlog 18</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-18/</link>
      <description>&lt;p&gt;It&#39;s been a while since I posted anything. In the past couple months, Reflector has been on the back burner for me, but not completely forgotten. I&#39;m not sure if I&#39;ll be going back to weekly updates like before, but if not I&#39;ll aim for monthly.&lt;/p&gt;
&lt;p&gt;The latest addition is emitting smoke from buildings, so you can see at a glance what is active.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-18/Kl9UvlCFJZ-768.webp&quot; alt=&quot;Smoke&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot;&gt;&lt;/p&gt;
&lt;p&gt;New since last update:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;All sprites switched from 16x16 to 24x24 pixels, many redesigned from scratch&lt;/li&gt;
&lt;li&gt;Ability to toggle between zoomed in and zoomed out&lt;/li&gt;
&lt;li&gt;Cleaned up display priorities of the various entities (which things are rendered on top)&lt;/li&gt;
&lt;li&gt;Smoke! Buildings can emit smoke from multiple locations based on various conditions, such as how many colonists are working&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Currently smoke is only implemented for the mine, but with the code in place, it will be simple to add smoke to the other production buildings. That is my next priority. After that, I&#39;ll work on making residences visibly occupied, by lighting up the windows when colonists are inside. With those two features, I&#39;m hoping that most important information will be visible without the need for any sort of &quot;inspect&quot; action.&lt;/p&gt;</description>
      <pubDate>Fri, 01 May 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-18/</guid>
    </item>
    <item>
      <title>Reflector Devlog 17</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-17/</link>
      <description>&lt;p&gt;This week I finished up the new mechanics and content for alpha 2! The biggest change was implementing job priorities with the ability to disable jobs for specific buildings. In the gif below, you can see me prioritize farming over mining, cause colonists to go from the mines to the farms. I then disable two of the farms, and those colonists go back to the mines.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-17/UsQ7zw0jSD-920.webp&quot; alt=&quot;Job Priorities in Action&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;598&quot;&gt;&lt;/p&gt;
&lt;p&gt;Changes this week:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Colonists now fill jobs for prioritized job types first&lt;/li&gt;
&lt;li&gt;Each night, colonists of high-priority jobs get the first pick of residences, so colonists with high priority jobs will generally end up living closer to where they work&lt;/li&gt;
&lt;li&gt;Added the ability to disable jobs on a building-by-building basis&lt;/li&gt;
&lt;li&gt;Added the free-to-build mining spot; produces less metal than a mine&lt;/li&gt;
&lt;li&gt;Removed the mining action (this was intended to be used as source of metal if all mines got destroyed but the player didn&#39;t have enough metal to build a new one; it caused confusion and is no longer necessary with the mining spot)&lt;/li&gt;
&lt;li&gt;Added a greenhouse, which can be placed on any terrain and produces more food than a farm, but consumes power&lt;/li&gt;
&lt;li&gt;Added an advanced splitter, which splits any incoming beam into the other 3 directions&lt;/li&gt;
&lt;li&gt;Changed immigration so colonists arrive in a small groups at the start of each day, instead of one at a time throughout day and night&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next week I don&#39;t anticipate much coding. Instead, I&#39;ll be working on converting the sprites from 16x16 to 24x24 pixels, finishing a couple design books, and preparing for the UI redesign.&lt;/p&gt;
&lt;p&gt;Here are my goals for the redesign:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Switch to 24x24 pixel tiles&lt;/li&gt;
&lt;li&gt;Full intuitive mouse support&lt;/li&gt;
&lt;li&gt;Full intuitive keyboard support&lt;/li&gt;
&lt;li&gt;Generally more polished UI&lt;/li&gt;
&lt;li&gt;Make as much of the game state readable by looking at the map, no &quot;inspect&quot; necessary&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Sat, 15 Feb 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-17/</guid>
    </item>
    <item>
      <title>Reflector Devlog 16</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-16/</link>
      <description>&lt;p&gt;My main task this week was the interface for setting job priorities. Since I&#39;m going to be overhauling the entire UI, I decided to start introducing some of the technologies I&#39;m planning on using for that. For now, things are a messy mix of the new and the old. Here&#39;s the current job priority UI:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-16/i_SU1RQzFd-920.webp&quot; alt=&quot;Job Priority UI&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;594&quot;&gt;&lt;/p&gt;
&lt;p&gt;Changes this week:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Changed lasers so they can shoot over low things such as colonists and farms&lt;/li&gt;
&lt;li&gt;Added ability to remove buildings (except occupied houses)&lt;/li&gt;
&lt;li&gt;Added a basic projector, with a shorter range than the normal projector&lt;/li&gt;
&lt;li&gt;Set up tailwindcss for future style overhaul&lt;/li&gt;
&lt;li&gt;Initial implementation of job priority UI (colonists currently ignore job priority)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next up:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Make colonists respect job priorities&lt;/li&gt;
&lt;li&gt;Add ability to disable jobs for individual buildings&lt;/li&gt;
&lt;li&gt;Add advanced splitter&lt;/li&gt;
&lt;li&gt;Add greenhouse&lt;/li&gt;
&lt;li&gt;Add mining spot (less efficient than mine but free to build)&lt;/li&gt;
&lt;li&gt;Remove mining action (manually mining vs building a mine has been a source of confusion)&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Fri, 07 Feb 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-16/</guid>
    </item>
    <item>
      <title>Reflector Devlog 15</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-15/</link>
      <description>&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-15/l2lQLf-UhP-768.webp&quot; alt=&quot;Colony with wind and solar power in the northwest&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot;&gt;&lt;/p&gt;
&lt;p&gt;I&#39;m continuing to work on new content and mechanics for Alpha 2 .Here&#39;s a summary of the changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Added solar panels, which produce power during the day&lt;/li&gt;
&lt;li&gt;Added windmills, which produce power if there is nothing blocking any adjacent position&lt;/li&gt;
&lt;li&gt;Projectors now consume power, otherwise they stop working&lt;/li&gt;
&lt;li&gt;Increased map size&lt;/li&gt;
&lt;li&gt;Lasers now only hit &#39;tall&#39; things; lasers can now shoot over farms and colonists&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;My remaining features part of my Alpha 2 to-do list is getting small, so I&#39;ll share it here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Split projector into basic and advanced (basic has shorter range)&lt;/li&gt;
&lt;li&gt;Split splitter into basic and advanced (basic needs power)&lt;/li&gt;
&lt;li&gt;Add ability to prioritize job types&lt;/li&gt;
&lt;li&gt;Add ability to forbid / turn off jobs for specific building&lt;/li&gt;
&lt;li&gt;Rework immigration mechanics (not fully decided here)&lt;/li&gt;
&lt;li&gt;Rework job and house assigning to be more efficient (for in-game logistics, not computationally)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That should take me 2-3 weeks. After that, I&#39;ll shift towards balance and UX. For Alpha 1, this phase took a much longer than I expected. One reason is that it frankly isn&#39;t as much fun as working on new content and mechanics. The second reason is that while playtesting, I kept on finding new UX annoyances to fix. I expect both reasons to come into play again for Alpha 2, but moreso. The complexity the base-management mechanics has increased a lot, so that will make good balance and good UX much harder.&lt;/p&gt;
&lt;p&gt;Additionally, I&#39;ve decided that this is the release to tackle changing the map size and adding full mouse controls, since I suspect both will become exponentially more difficult as the game continues to grow. Changing the map size also means changing the tile size to 24x24 pixels, so I&#39;ll need to redo all assets. This is going to be a big one, folks.&lt;/p&gt;</description>
      <pubDate>Fri, 31 Jan 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-15/</guid>
    </item>
    <item>
      <title>Reflector Devlog 14</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-14/</link>
      <description>&lt;p&gt;This week I added the last of new resources for alpha 2: power and refined metal.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Power is created by colonists working in power plants&lt;/li&gt;
&lt;li&gt;Refined metal is created by colonists working at furnaces, but consumes metal and power to make&lt;/li&gt;
&lt;li&gt;Splitters and projectors are now built with refined metal instead of metal&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;m also trying out infinitely strong lasers. Before, each laser beam had limited strength, and each time they hit an enemy or were split, they lost one strength. This worked fine, but I really want to emphasize the laser manipulation mechanics. Now each beam can go through as many enemies as you manage to direct it towards. Each shot now costs power, to further incentivize killing multiple enemies with one shot. If you run out of power, you can still shoot, but it will only be a 1 strength beam. I might change this back while balancing alpha 2, but so far it is looking promising.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-14/uBDrDaa_bJ-768.webp&quot; alt=&quot;Bustling Colony&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot;&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 24 Jan 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-14/</guid>
    </item>
    <item>
      <title>Reflector Devlog 13</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-13/</link>
      <description>&lt;p&gt;This week I added the first of the new resources: food! Here&#39;s how it works:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fertile land has been added as a new terrain. It is placed near water during map generation.&lt;/li&gt;
&lt;li&gt;A farm building has been added, which can be built only on fertile land.&lt;/li&gt;
&lt;li&gt;Each farm provides one job for a colonist, which produces 0.2 food when worked.&lt;/li&gt;
&lt;li&gt;On the last turn of each day, all colonists need to consume 1 food. If there&#39;s not enough, the colony loses 1 morale.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-13/tFr8Pvkbm4-768.webp&quot; alt=&quot;Colony with farms&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;768&quot; height=&quot;768&quot;&gt;&lt;/p&gt;
&lt;p&gt;Those numbers will likely change once I start working on balance, but first I&#39;m going to add more resources.&lt;/p&gt;</description>
      <pubDate>Sat, 18 Jan 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-13/</guid>
    </item>
    <item>
      <title>Reflector Devlog 12</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-12/</link>
      <description>&lt;p&gt;The holidays were full of cooking, family, and driving across the country. This last week, I got back to working on Reflector. Colonists will now pitch tents if there aren&#39;t enough residences. During the day, they go work in the mines, which no longer produce metal on their own. If there&#39;s no work, they&#39;ll wander around aimlessly.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-12/mWcQ0FIPZm-833.webp&quot; alt=&quot;Colonists going to the mines&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;833&quot; height=&quot;833&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now that the framework is in place for jobs, I&#39;ll add some new buildings, jobs, and resource: food, oil, power, refined metal. That will probably take a couple weeks. After that, I plan on making each shot cost power and see how that goes. Then, it will be back UX improvements and balance for the next release.&lt;/p&gt;</description>
      <pubDate>Fri, 10 Jan 2020 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-12/</guid>
    </item>
    <item>
      <title>Reflector Devlog 11</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-11/</link>
      <description>&lt;p&gt;This week I got started adding colonists to the map (instead of just hiding in their houses and teleporting when they find a better house). For now, they just wander during the day, and return home at night, if they can find a home. Next week, I&#39;ll make them throw up tents if needed, and go work in the mines during the day.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-11/f8D_OENOvx-774.webp&quot; alt=&quot;Colonists returning home&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;774&quot; height=&quot;774&quot;&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 20 Dec 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-11/</guid>
    </item>
    <item>
      <title>Reflector Devlog 10</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-10/</link>
      <description>&lt;p&gt;This week was devoted to work beyond the game itself. Now with that out of the way, I&#39;m excited to start working on new mechanics and content again, for the first time since mid October!&lt;/p&gt;
&lt;p&gt;Here&#39;s what I got done this week:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Added many screenshots to the itch.io page&lt;/li&gt;
&lt;li&gt;Restyled blog to have a dark theme, more fitting the game&lt;/li&gt;
&lt;li&gt;Added an about me page to the blog&lt;/li&gt;
&lt;li&gt;Added a nav bar, with many relevant links, including to the RSS feed&lt;/li&gt;
&lt;li&gt;Added an introduction section the main blog page&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Fri, 13 Dec 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-10/</guid>
    </item>
    <item>
      <title>Reflector Devlog 9</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-9/</link>
      <description>&lt;p&gt;This week I finished up the post-release refactoring I wanted to do. There&#39;s always more that could be done, but I&#39;m going to call it there for now.&lt;/p&gt;
&lt;p&gt;I&#39;ve decided that before I start working on the mechanics for alpha 2, I&#39;m going to make some changes to the blog and the itch.io page to better showcase the game. I imagine that will last me the week, but hopefully not beyond.&lt;/p&gt;</description>
      <pubDate>Fri, 06 Dec 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-9/</guid>
    </item>
    <item>
      <title>Reflector Devlog 8</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-8/</link>
      <description>&lt;p&gt;I&#39;ve taken this first week after the alpha 1 release to reward myself with some code refactoring. I&#39;ve cleaned up a lot of things that were bothering, and I have few more things that I should finish up this week. Then I&#39;ll be putting the colonists to work.&lt;/p&gt;
&lt;p&gt;Last weekend I created a RogueBasin page and release announcement for my game. It was a little troublesome (due to some strict automatic spam prevention they have) and I wasn&#39;t sure if it would end up being worth it. However, according the analytics provided by itch.io, RogueBasin is my biggest source of traffic after itch.io itself. So you other roguelike devs out there, go and make yourself a RogueBasin page!&lt;/p&gt;</description>
      <pubDate>Fri, 29 Nov 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-8/</guid>
    </item>
    <item>
      <title>Reflector: Laser Defense Alpha 1 Release</title>
      <link>https://oatmeal.gg/blog/reflector-release-1.0.0/</link>
      <description>&lt;h1&gt;Alpha 1: They Come at Night&lt;/h1&gt;
&lt;p&gt;You can now play the first alpha release over on itch.io!&lt;/p&gt;
&lt;p&gt;Here&#39;s what it all includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Defend your colony from the waves of drones that attack at night&lt;/li&gt;
&lt;li&gt;Make the most of every shot by manipulating lasers with splitters and projectors&lt;/li&gt;
&lt;li&gt;Mine metal so you can expand your colony&lt;/li&gt;
&lt;li&gt;Build residences to control where your population lives&lt;/li&gt;
&lt;li&gt;Build walls to buy yourself a few turns before the enemies break through&lt;/li&gt;
&lt;li&gt;Build projectors to expand the area where you can place reflectors&lt;/li&gt;
&lt;li&gt;Build mines so you don&#39;t need to mine by hand&lt;/li&gt;
&lt;li&gt;Randomly generated maps with mountains and lakes to keep things interesting game to game&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;Up Next&lt;/h1&gt;
&lt;p&gt;I&#39;m going to take some time to focus on code refactoring and addressing any bugs or balance issues that come up. After a bit of that, I&#39;ll start working on the next release which will be focused on expanding the economy beyond just metal and giving your colonists some things to do.&lt;/p&gt;</description>
      <pubDate>Fri, 22 Nov 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-release-1.0.0/</guid>
    </item>
    <item>
      <title>Reflector Devlog 7</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-7/</link>
      <description>&lt;p&gt;I&#39;ll keep this one nice and short. This week I made a lot of small balance and UX changes. The first alpha is now out and available on itch.io!&lt;/p&gt;</description>
      <pubDate>Fri, 22 Nov 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-7/</guid>
    </item>
    <item>
      <title>Reflector Devlog 6</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-6/</link>
      <description>&lt;p&gt;This was a pretty light week, with just a few small UX improvements.&lt;/p&gt;
&lt;p&gt;Here&#39;s what&#39;s new:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Remember the last direction you were aiming when activated laser&lt;/li&gt;
&lt;li&gt;By default, no longer jump over invalid locations when placing reflectors or buildings&lt;/li&gt;
&lt;li&gt;Show red border when current target location is invalid&lt;/li&gt;
&lt;li&gt;Hold shift to jump over invalid locations&lt;/li&gt;
&lt;li&gt;Added ability to remove single reflector (instead of only having ability to remove all reflectors)&lt;/li&gt;
&lt;li&gt;Added support for moving with numpad&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Fri, 15 Nov 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-6/</guid>
    </item>
    <item>
      <title>Reflector Devlog 5</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-5/</link>
      <description>&lt;p&gt;Balancing and playtesting continues. There is now a night and day cycle. Currently that only means that enemies spawn at night. In the future other systems will integrate with night and day, but it made sense to add it now while balancing the timing of enemy waves. As I&#39;m playing the game more, I&#39;ve found a couple more UX enhancements I&#39;d like to make, so this next week I&#39;ll work on those in addition to more balancing.&lt;/p&gt;
&lt;p&gt;Nothing visual to share this week, but development builds are now available! The official &quot;stable&quot; releases will be on itch.io, but if anyone wants to try out the latest version, that&#39;s now available.&lt;/p&gt;
&lt;p&gt;Here&#39;s what&#39;s new:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Map generation now produces a consistent amount water/mountain/ore&lt;/li&gt;
&lt;li&gt;Day and night cycle&lt;/li&gt;
&lt;li&gt;Enemies spawn at night&lt;/li&gt;
&lt;li&gt;Small fixes and tweaks&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Fri, 08 Nov 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-5/</guid>
    </item>
    <item>
      <title>Reflector Devlog 4</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-4/</link>
      <description>&lt;p&gt;This was a bit of a light week. I finished up all the UX changes I want for the initial release and got started with some balancing. It&#39;s all playtesting from here on out until release.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-4/RizO9BYDL9-920.webp&quot; alt=&quot;screenshot&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;605&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here&#39;s what&#39;s new:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New sprite for player&lt;/li&gt;
&lt;li&gt;New graphics for water&lt;/li&gt;
&lt;li&gt;Added description to game opening page&lt;/li&gt;
&lt;li&gt;Added a dialog on game end with a restart button&lt;/li&gt;
&lt;li&gt;Changed all references of pops to colonists&lt;/li&gt;
&lt;li&gt;Disabled all game controls on game over&lt;/li&gt;
&lt;li&gt;Increased laser power&lt;/li&gt;
&lt;li&gt;Increased map size&lt;/li&gt;
&lt;li&gt;Restyling of interface to better handle different screen sizes&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Fri, 01 Nov 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-4/</guid>
    </item>
    <item>
      <title>Reflector Devlog 3</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-3/</link>
      <description>&lt;p&gt;This week was focused on UX changes. There&#39;s a couple more UX changes I want to make, and then I&#39;ll shift focus to playtesting and balancing for an initial release. I&#39;ll likely find some bugs and papercuts along the way, but I&#39;m hoping to have this out in a couple weeks.&lt;/p&gt;
&lt;p&gt;Here&#39;s what&#39;s new:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Changed the ore graphic to distinguish it from normal ground by more than just color&lt;/li&gt;
&lt;li&gt;The player now turns into a corpse/skull when killed instead of disappearing&lt;/li&gt;
&lt;li&gt;Added very basic mouse controls (no interaction with the map yet)&lt;/li&gt;
&lt;li&gt;When placing reflectors or building, the target now jumps over invalid spots (this needs some tweaking though)&lt;/li&gt;
&lt;li&gt;When placing reflectors or building, it now shows valid spots with a dashed border and your currently targeted spot with a solid border&lt;/li&gt;
&lt;li&gt;Log a message if there are no valid spots in range&lt;/li&gt;
&lt;li&gt;Log a message if you cannot afford to build a building&lt;/li&gt;
&lt;li&gt;Added an inspect action&lt;/li&gt;
&lt;li&gt;Clearly distinguish actions which do not take a turn&lt;/li&gt;
&lt;li&gt;Added tooltips to some actions&lt;/li&gt;
&lt;li&gt;Game now autosaves every turn&lt;/li&gt;
&lt;li&gt;Added a main menu where you can select new game or load game&lt;/li&gt;
&lt;li&gt;Show a warning if the current version does not match the saved game version&lt;/li&gt;
&lt;li&gt;I&#39;m still playing around with color palettes&lt;/li&gt;
&lt;li&gt;Various style tweaks, text changes, and bug fixes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I don&#39;t feel like taking a bunch of screenshots for all of the above (and that would probably be pretty boring), so instead here&#39;s a gif of the latest:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-3/a2KJN9qvbc-920.webp&quot; alt=&quot;gameplay&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;622&quot;&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 25 Oct 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-3/</guid>
    </item>
    <item>
      <title>Reflector Devlog 2</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-2/</link>
      <description>&lt;p&gt;This week I finished up all the mechanics and game systems I want for the initial version. I&#39;ll probably spend most of next week on some UX improvements before transitioning into balance changes.&lt;/p&gt;
&lt;p&gt;Here&#39;s what&#39;s new:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Walls are stronger now. They turn into damaged walls when hit instead of being destroyed right away.
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-2/Y9IQRcrxuf-687.webp&quot; alt=&quot;walls&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;687&quot; height=&quot;679&quot;&gt;&lt;/li&gt;
&lt;li&gt;Random map generation with three types of terrain
&lt;ul&gt;
&lt;li&gt;Mountains block all movement and are indestructible&lt;/li&gt;
&lt;li&gt;Water also blocks movement but your lasers can shoot over them&lt;/li&gt;
&lt;li&gt;Ore doesn&#39;t affect movement but can be mined either manually or by mines (which must now be built on ore terrain instead of anywhere)
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-2/sBxDpMIwBn-672.webp&quot; alt=&quot;map&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;672&quot; height=&quot;672&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Building now takes a turn (placing reflectors does not)&lt;/li&gt;
&lt;li&gt;Added new action to remove all reflectors&lt;/li&gt;
&lt;li&gt;Added new action to manually mine (if next to ore)&lt;/li&gt;
&lt;li&gt;Trying out a new color palette&lt;/li&gt;
&lt;li&gt;Rendering of reflecting and splitting lasers, instead of only the straight parts. It now looks much more satisfying when you have complex laser shenanigans.
&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-2/Efe5J9Iv25-672.webp&quot; alt=&quot;lasers&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;672&quot; height=&quot;672&quot;&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <pubDate>Fri, 18 Oct 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-2/</guid>
    </item>
    <item>
      <title>Reflector Devlog 1</title>
      <link>https://oatmeal.gg/blog/reflector-devlog-1/</link>
      <description>&lt;p&gt;Progress has been steady this week. For the first time since I purged most of the 7DRL content, things are starting to feel like a game again. Here&#39;s the changelog for the week:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Implemented basic enemy that targets nearest destructible object&lt;/li&gt;
&lt;li&gt;Basic building mechanics&lt;/li&gt;
&lt;li&gt;Basic resource mechanics&lt;/li&gt;
&lt;li&gt;Mine building, which produces metal (the only resource for now, needed to build other things)&lt;/li&gt;
&lt;li&gt;Wall building, basic barrier against enemies&lt;/li&gt;
&lt;li&gt;Residence building, which can house up to three pops (otherwise they will place a tent somewhere random)&lt;/li&gt;
&lt;li&gt;Pops migrate to more desirable houses (currently just from starting tent to new residence building, but the system should work with new buildings too)&lt;/li&gt;
&lt;li&gt;Projectors, which allow you to place reflectors around them, instead of only around yourself&lt;/li&gt;
&lt;li&gt;Reflectors must be within range of you or a projector, otherwise they are destroyed&lt;/li&gt;
&lt;li&gt;Fixed a bug where valid building locations would stop being displayed after you tried to place a building in an invalid spot&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Next week, I&#39;m going to add some terrain and map generation, and then transition away from new mechanics and systems and into UX and balance. I&#39;m hoping to have a reasonably balanced first iteration in a couple weeks time.&lt;/p&gt;
&lt;p&gt;And since it&#39;s been requested, here&#39;s a gif:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflector-devlog-1/CwlGytQvg_-920.webp&quot; alt=&quot;GIF&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;920&quot; height=&quot;612&quot;&gt;&lt;/p&gt;</description>
      <pubDate>Fri, 11 Oct 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflector-devlog-1/</guid>
    </item>
    <item>
      <title>Annoucing Reflector: Laser Defense</title>
      <link>https://oatmeal.gg/blog/annoucing-reflector-laser-defense/</link>
      <description>&lt;p&gt;In Reflector: Laser Defense you&#39;ll be in charge of developing and defending a colony on a hostile planet. You&#39;ll have no army though; just yourself and your laser gun.&lt;/p&gt;
&lt;p&gt;Planned Features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Classic roguelike turn-based grid-based gameplay where you directly control only one person&lt;/li&gt;
&lt;li&gt;Manipulate laser beams with reflectors and splitters to make the most of each shot&lt;/li&gt;
&lt;li&gt;Base building and resouce management&lt;/li&gt;
&lt;li&gt;An ever-growing population that presents its own challenges&lt;/li&gt;
&lt;li&gt;Mine and manufacture resources to support your settlement&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is not a full or final list. We&#39;ll see where the future brings us. But enough about plans. What do I have now?&lt;/p&gt;
&lt;p&gt;Reflector: Laser Defense is building off of Reflector RL, a 7DRL I made in March. Since then, I&#39;ve refactored the code so that I have sturdier foundation. I&#39;ve stripped out most of the content and added some of the core elements that will make up R:LD: enemy waves, a growing population, laser manipulation. It is technically a complete game right now, which you can win and lose, though it is extremely unbalanced. Next up I&#39;ll be working on the building and resource mechanics and then balancing that to a minimal but hopefully fun state that I can iterate from.&lt;/p&gt;</description>
      <pubDate>Fri, 04 Oct 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/annoucing-reflector-laser-defense/</guid>
    </item>
    <item>
      <title>Reflecting on Reflector</title>
      <link>https://oatmeal.gg/blog/reflecting-on-reflector/</link>
      <description>&lt;p&gt;&lt;img src=&quot;https://oatmeal.gg/blog/reflecting-on-reflector/HcVyga5oeY-630.webp&quot; alt=&quot;Screenshot&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;630&quot; height=&quot;501&quot;&gt;&lt;/p&gt;
&lt;p&gt;This year I completed my first 7DRL, Reflector RL (source). The idea was a game where your only weapon is a laser that can be fired in the four cardinal directions, but your enemies are able to move and attack in all eight directions. To make up for your lack of maneuverability, you need to place reflectors and splitters to manipulate your lasers.&lt;/p&gt;
&lt;h3&gt;The Good&lt;/h3&gt;
&lt;p&gt;I wanted to keep the game focused on manipulating the laser beams. Overall, I think it works as a core mechanic, and creates some interesting and unique scenarios. Early in the week, you could get away without actually using the reflectors and splitters much. More enemies and longer recharge times on the weapons created more pressure. If you&#39;re only killing one enemy per shot, you won&#39;t last long.&lt;/p&gt;
&lt;p&gt;I decided to stick with technologies I know: Typescript, React, Redux, and rot.js. My goal was to make a game, not learn a new programming language. Typescript gave me some troubles at first, but once set up, the safety and editor support it provides saved me from lots of bugs. I plan to stick with this set up for future roguelike projects.&lt;/p&gt;
&lt;p&gt;This is my first complete game, playable from start to finish, and I think it&#39;s fun. What more could I ask? My previous projects got bogged down in the possibilities and technology, but the 7DRL format forced me to keep my scope limited. I now have a solid base to iterate on, both mechanically for this game, but also technologically for future projects.&lt;/p&gt;
&lt;h3&gt;The Bad&lt;/h3&gt;
&lt;p&gt;I&#39;m not sure how balanced it is. In my initial plan, I reserved the final three days of the challenge for balance. I ended up with closer to a day and a half. I have beaten the game once, but I haven&#39;t played it enough to know how much of that was luck. Time will tell.&lt;/p&gt;
&lt;p&gt;The player doesn&#39;t move around quite as much as I want. On each level, I end up spending most of the time in whatever corner of the map I spawned in. I introduced both the teleporter gun and on-map teleporters to help with this issue. It&#39;s definitely better than it was before, but I&#39;m still not quite satisfied.&lt;/p&gt;
&lt;p&gt;Around 10pm the final night, I realized I should test the game with other screen sizes. That led to a mad dash to make the UI fit on screens that aren&#39;t giant. It now fits on most screens, but still isn&#39;t very responsive. Definitely going to look at that earlier next time.&lt;/p&gt;
&lt;h3&gt;The Future&lt;/h3&gt;
&lt;p&gt;I am going to keep working on Reflector. I have ideas for more content and mechanics that I didn&#39;t have time to implement. However, before I get to those, I&#39;m going to clean up the code a bit, add graphical tiles, and making the game mobile friendly (I want more roguelikes on my phone). Then it&#39;s on to balance and more content.&lt;/p&gt;</description>
      <pubDate>Sat, 16 Mar 2019 24:00:00 GMT</pubDate>
      <dc:creator>Michael Moore</dc:creator>
      <guid>https://oatmeal.gg/blog/reflecting-on-reflector/</guid>
    </item>
  </channel>
</rss>