<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>locke&#39;s dev blog</title>
    <link>https://lockeb.dev/</link>
    <description>Recent content on locke&#39;s dev blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-au</language>
    <managingEditor>byzxor@tuta.io (byzxor_)</managingEditor>
    <webMaster>byzxor@tuta.io (byzxor_)</webMaster>
    <lastBuildDate>Thu, 13 Aug 2026 10:51:00 +0000</lastBuildDate>
    <atom:link href="https://lockeb.dev/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>The Lab is back...</title>
      <link>https://lockeb.dev/posts/the-lab-is-back/</link>
      <pubDate>Thu, 13 Aug 2026 10:51:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/the-lab-is-back/</guid>
      <description>&lt;p&gt;So it seems I&amp;rsquo;ve managed to get something working with my homelab in a way that doesn&amp;rsquo;t disgust me (too much). In fact, some of it is really quite cool. The main downsides however are pretty annoying, but I&amp;rsquo;ll get to them. Also this is nowhere near finished, but there is now a finish line.&lt;/p&gt;&#xA;&lt;h2 id=&#34;isnt-this-the-nth-time-youve-done-this&#34;&gt;Isn&amp;rsquo;t this the nth time you&amp;rsquo;ve done this?&lt;/h2&gt;&#xA;&lt;p&gt;Yes! And what always happens is that I give up having to deal with it for one reason or another, usually caused by a stupid decision I made at some point. Thankfully, with all that prior experimentation I&amp;rsquo;ve arrived at a few nice decisions:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>So it seems I&rsquo;ve managed to get something working with my homelab in a way that doesn&rsquo;t disgust me (too much). In fact, some of it is really quite cool. The main downsides however are pretty annoying, but I&rsquo;ll get to them. Also this is nowhere near finished, but there is now a finish line.</p>
<h2 id="isnt-this-the-nth-time-youve-done-this">Isn&rsquo;t this the nth time you&rsquo;ve done this?</h2>
<p>Yes! And what always happens is that I give up having to deal with it for one reason or another, usually caused by a stupid decision I made at some point. Thankfully, with all that prior experimentation I&rsquo;ve arrived at a few nice decisions:</p>
<ol>
<li>You don&rsquo;t need to use ArgoCD/FluxCD for something <em>this</em> simple</li>
<li>Maybe I don&rsquo;t need to self-host everything I think looks cool</li>
<li>Paying a little bit of cash to make things easier is perhaps fine</li>
</ol>
<h3 id="1">1</h3>
<p>This took me by surprise. The plan was to use FluxCD since it makes more sense for a small setup like what I&rsquo;m doing. But the sheer amount of stuff that needed to be done just for that was too much. I dialed my requirements back a bit and decided that a well documented README with everything handled by <code>helm</code> manually would be sufficient. We will see in a few months how that decision has been.</p>
<h3 id="2">2</h3>
<p>This is a me problem. There are so many things that could be self-hosted. Taking a few seconds back to ask &ldquo;why&rdquo; and &ldquo;how&rdquo; together can usually stop any sort of impulse. To this end I started trying to devise a list of what is <em>essential</em>:</p>
<ul>
<li>A personal wiki</li>
<li>CI for Codeberg</li>
<li>RSS Aggregator (for reasons that will be discussed in a later blog post)</li>
</ul>
<p>This is a weirdly short list, but that wiki (an <a href="https://otterwiki.com/">Otterwiki</a>) is doing a lot of heavy lifting (like where I am currently writing this) that I might write up exactly <em>how</em> at some point. My main questions to help narrow things down are:</p>
<ul>
<li>Does it replace a paid/dodgy/sloppy product?</li>
<li>Is it allowed to go down for X days?</li>
<li>Does it need to be hosted?</li>
<li>Is it easy to recover after catastrophe?</li>
</ul>
<p>Generally if the answer is all yeses, it goes onto my shortlist. A key word in that first question is &lsquo;replace&rsquo;. I don&rsquo;t particularly want to add a new application to what I already have UNLESS it&rsquo;s absolutely critical. In this case, the <a href="https://docs.codeberg.org/ci/actions/">ForgeJo Actions</a> for use on Codeberg is one of very few exceptions I will be making.</p>
<p>Alas, while still paring everything down, there are some required essentials on top of this:</p>
<ul>
<li>Status and alerting system</li>
<li>Some SSO provider</li>
<li>A tunnel</li>
</ul>
<p>But these are running on the VPS machines (yes, plural) so maybe it doesn&rsquo;t count.</p>
<p>Of course in addition to these I will host my own services here (currently just <a href="https://lfm-grid.lockelhost.xyz/">LFM-GRID</a> and <a href="https://codeberg.org/byzxor/snagg">snagg</a>). Hopefully more coming soon&hellip;</p>
<h3 id="3">3</h3>
<p>Unfortunately homelabbing isn&rsquo;t free. Even with an old &lsquo;dead&rsquo; laptop. And it gets less free when you want to make it more secure. So I&rsquo;ve decided to pay the 11€ a month for a pair of VPSs at <a href="https://signup.upcloud.com/?promo=57TCW9">UpCloud</a> (that&rsquo;s a referral link BTW just in case I&rsquo;ve convinced you :) ). One VPS runs the SSO, status, notification, and health services. The other runs <a href="https://pangolin.net/">Pangolin</a>. They are separated for 2 reasons: firstly, Pangolin is hungry. Secondly, I would rather isolate my health checks and notifications so I can be informed when anything dies (which reminds me, I need a Dead Mans Switch on the status VPS).</p>
<h4 id="newt">Newt</h4>
<p>How I&rsquo;m using Pangolin is by running <code>Newt</code> at the system level and exporting my services by port-forwarding (automatically) on those machines. However, running AlmaLinux (with SELinux) proved to be a bit of a shit for <code>Newt</code>, mainly because I&rsquo;m a SELinux noob. <code>chcon -t bin_t newt</code> did the trick. If I decide to also forward my music server (on a different machine) it&rsquo;ll be quite a bit easier since that&rsquo;s just boring-old-Debian.</p>
<h2 id="iocaine">Iocaine</h2>
<p>I had an idea to put <a href="https://iocaine.madhouse-project.org/">Iocaine</a> everywhere. I &rsquo;liked&rsquo; Anubis, but considering how &lsquo;sloppy&rsquo; it now is and how it interrupts humans instead of scrapers. For my status VPS I&rsquo;m using Caddy as the reverse proxy because it was easy. Putting Iocaine on there was also very easy. How nice. On the Pangolin VPS I&rsquo;m using Traefik (since Pangolin defaults to that). Thankfully there was a guide on installing Iocaine as middleware there. So now every site I forward via Pangolin has Iocaine running with it! I currently have it configured at its most basic but I am thinking of switching it to use &lsquo;<a href="https://git.madhouse-project.org/iocaine/nam-shub-of-enki">Nam Shub of Enki</a>&rsquo; instead of the default QMK. I also need to forward the metrics somewhere easy so I can check them out easily.</p>
<h2 id="future">Future</h2>
<p>I will likely add some more things to my &ldquo;essential services&rdquo; list soon, with the current contender being a todo/planning tool, and a GTS instance is looking might tempting. I&rsquo;m sure there&rsquo;s many more quirks I will have to deal with (like proper secrets management, which I think I&rsquo;ll be going down the SOPS road again) but right now things seem nice.</p>
<h3 id="an-idea">An idea</h3>
<p>Someone I follow on Mastodon had the idea of powering off services when you don&rsquo;t really need them, but for mental health reasons. I like this idea quite a bit, but since I plan on hosting some publicly accessible things I would have to focus on scaling down based on load instead of outright killing things. I will probably give <a href="https://keda.sh/">Keda</a> a go at some point, although not sure how to get that to behave with the Forgejo runner. Although making some &lsquo;power-off/power-on&rsquo; endpoint could be kinda neat&hellip;.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Reflashing my... everything</title>
      <link>https://lockeb.dev/posts/reflashing-my-everything/</link>
      <pubDate>Sat, 08 Aug 2026 11:22:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/reflashing-my-everything/</guid>
      <description>&lt;p&gt;As is tradition when I take my holidays, I spend quite sometime configuring the machines around the apartment. Usually this is followed up with some homelab experiments I give up on in a few days. I thought I&amp;rsquo;d write some things about this process here and some changes I&amp;rsquo;ve made:&lt;/p&gt;&#xA;&lt;blockquote&gt;&#xA;&lt;p&gt;Apologies in advance for the Cosmere names&lt;/p&gt;&#xA;&lt;/blockquote&gt;&#xA;&lt;h2 id=&#34;the-media-server-oathgate&#34;&gt;The Media Server (&lt;code&gt;oathgate&lt;/code&gt;)&lt;/h2&gt;&#xA;&lt;p&gt;This is a NUC from 2015 that I&amp;rsquo;ve increased the RAM, the SSD and the HDD over the years. It sites behind the TV and serves Jellyfin and Navidrome internally. It has run Ubuntu Server since around 2020 when I decided that it should never be plugged into any monitor (except for debugging purposes). This time, I&amp;rsquo;ve decided to go vanilla Debian because, well, I don&amp;rsquo;t trust Ubuntu any longer, and to be fair the &amp;ldquo;please pay&amp;rdquo; warnings in Ubuntu Server have been giving me the shits for about a year.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>As is tradition when I take my holidays, I spend quite sometime configuring the machines around the apartment. Usually this is followed up with some homelab experiments I give up on in a few days. I thought I&rsquo;d write some things about this process here and some changes I&rsquo;ve made:</p>
<blockquote>
<p>Apologies in advance for the Cosmere names</p>
</blockquote>
<h2 id="the-media-server-oathgate">The Media Server (<code>oathgate</code>)</h2>
<p>This is a NUC from 2015 that I&rsquo;ve increased the RAM, the SSD and the HDD over the years. It sites behind the TV and serves Jellyfin and Navidrome internally. It has run Ubuntu Server since around 2020 when I decided that it should never be plugged into any monitor (except for debugging purposes). This time, I&rsquo;ve decided to go vanilla Debian because, well, I don&rsquo;t trust Ubuntu any longer, and to be fair the &ldquo;please pay&rdquo; warnings in Ubuntu Server have been giving me the shits for about a year.</p>
<p>I&rsquo;ve also decided to replace Navidrome with <a href="https://github.com/epoupon/lms">LMS</a> almost entirely out of virtue that it&rsquo;s not sloppy. The added <code>MusicNN</code> stuff will be interesting (if it ever finishes processing).</p>
<p>In an ideal world this would be connected to some network-attached-storage. Alas, the media now sits on an external HDD. This is not ideal, but I can live with it for now. It&rsquo;s not as if NASs and drives are going to get cheaper any time soon&hellip;</p>
<h2 id="the-homelab-coppermind">The Homelab (<code>coppermind</code>)</h2>
<p>This is a lower-end gaming laptop from 2019. Last time I went through this dance I used <code>proxmox</code> and started up various VMs to do <em>stuff</em>. This became annoying and complicated to the point that I just gave up on it. This time we&rsquo;re using Alma Linux because I quite like it for servers. I was thinking about a *BSD but decided that I wanted to put <code>k3s</code> on it, which ruled all of those out.</p>
<p>In my office I am yet to finalise where it will live. Currently it sits on a bookshelf behind me sitting precariously on a document storage tray from Ikea. This is part of a much large discussion/plan/expedition.</p>
<p>The curse of having a <code>k3s</code> set up very quickly is that my plan for what I&rsquo;m going to put on there is getting quite large, and the pod sprawl might become quite an issue. I also will attempt, for the 4th time, to use FluxCD instead of ArgoCD because a) it&rsquo;s lighter, b) pushing instead of pulling suits a low interaction system, and c) I get enough ArgoCD at work.</p>
<p>More on all of this later</p>
<h2 id="the-devtop-trha">The Devtop (<code>trha</code>)</h2>
<blockquote>
<p>gotcha, this is not Cosmerical, just <a href="https://trha.bandcamp.com/">music</a></p>
</blockquote>
<p>I&rsquo;ve already spoken about this <a href="https://byzxor.xyz/oh-ye-dell-become-chimera/">here</a> but it&rsquo;s Chimera Linux for reasons. This laptop is however still having problems, but according to 9 years of forum posts it could be caused by X of 7 problems. Joy.</p>
<h2 id="the-main-scadrial">The Main (<code>scadrial</code>)</h2>
<p>Continuing the thoughts from <a href="https://byzxor.xyz/getting-in-with-gentoo/">April</a> my main machine should be changing. But as much as I like the allure of Gentoo, this machine I would kinda like to be stable, since it&rsquo;s where the gaming happens (when it does). I was thinking either restarting with EndeavourOS or moving to CachyOS but they both suffer from slop and CachyOS is sponsored by a brand that I very much disagree with. I could just go vanilla Debian but Niri has some issues there. This is the hard one to figure out unfortunately. Gentoo is my number one choice here still, but this will keep eating at me. Alas, had I stuck to my plan where that dev laptop was going to be Gentoo while I learned it than this may be less of an issue. I guess now at least if Gentoo dies on this machine I can always use the devtop.</p>
<h2 id="too-many-things">Too Many Things</h2>
<p>Ok, so I have 4 different distros for 4 different machines. For posterity I guess I also have 2 Macs, but they are less for fun. And the Steam Deck, but I kinda wanna factory reset it since I did some dodgy shit when I first got it.</p>
<p>I have too many computers. The VPS that I&rsquo;ll be setting up doesn&rsquo;t count, but that&rsquo;s Debian at least.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Oh ye Dell, become Chimera</title>
      <link>https://lockeb.dev/posts/oh-ye-dell-become-chimera/</link>
      <pubDate>Sat, 01 Aug 2026 07:21:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/oh-ye-dell-become-chimera/</guid>
      <description>&lt;p&gt;(idk what that title is sorry)&lt;/p&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://byzxor.xyz/week-notes-29-2026/&#34;&gt;Recently&lt;/a&gt; I mentioned that I found an old laptop I found in my storage shelves and decided to do something with it. Initially the plan was OpenBSD but since I wanted to maybe put some games (Factorio) on it and have a working WM (this laptop has a Nvidia GPU), I decided to stay in Linux land. But this gave me an excuse:&lt;/p&gt;&#xA;&lt;p&gt;I could finally try out &lt;a href=&#34;https://chimera-linux.org/&#34;&gt;Chimera Linux&lt;/a&gt;. I&amp;rsquo;ve had my eye on this since the maintainer made a very clear anti-LLM statement (you know I&amp;rsquo;m a sucker for good ethics). It also has a whole bunch of other interesting features:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>(idk what that title is sorry)</p>
<p><a href="https://byzxor.xyz/week-notes-29-2026/">Recently</a> I mentioned that I found an old laptop I found in my storage shelves and decided to do something with it. Initially the plan was OpenBSD but since I wanted to maybe put some games (Factorio) on it and have a working WM (this laptop has a Nvidia GPU), I decided to stay in Linux land. But this gave me an excuse:</p>
<p>I could finally try out <a href="https://chimera-linux.org/">Chimera Linux</a>. I&rsquo;ve had my eye on this since the maintainer made a very clear anti-LLM statement (you know I&rsquo;m a sucker for good ethics). It also has a whole bunch of other interesting features:</p>
<ul>
<li>FreeBSD-like userland</li>
<li><code>dinit</code> instead of <code>systemd</code></li>
<li><code>apk</code> as the package manager</li>
<li><code>musl</code> instead of <code>glibc</code></li>
<li><code>doas</code> instead of <code>sudo</code></li>
</ul>
<figure>
    <img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/byzxor/p1000291ss.webp"
       alt="A laptop covered in stickers, mostly of black metal bands" height="60%", width="60%">
    <figcaption>TBF these stickers are a lot of the reason why I resurrected this</figcaption>
</figure>
<p>However, this laptop had a dead battery and a known overheating problem. Resolving these was surprisingly easy: iFixIt had a compatible battery in stock (70eu ouchie) and new thermal paste and thermal tape was about 15eu. There&rsquo;s a bunch of guides on how to make this laptop model more heat resilient which basically just boils down to &ldquo;put a more thermal tape in certain places&rdquo;. About 30 minutes of that, I had a laptop that could boot and run for several hours in Debian without randomly dying (foreshadowing). Now that the preliminary stuff was done I could move onto installing Chimera.</p>
<p>This was a far less painful process than that time I installed Gentoo in QEMU. However, there were some weird things. The <a href="https://chimera-linux.org/docs/installation">installation instructions</a> are <em>almost</em> amazing. They make assumptions and leave out some clarifying words that would have prevented 1 failed install. Thankfully, someone has a fork of Chimera which uses <code>glibc</code> instead of <code>musl</code> for compatability reasons, called &ldquo;<a href="https://casuarina.org/">Casuarina</a>&rdquo;. Why &ldquo;thankfully&rdquo;? Well the maintainer of this rewrote the install guide and added in some clarifications and missing info (albeit they went with <code>systemd-boot</code> instead of <code>GRUB</code> but ironically that section helped).</p>
<p>There&rsquo;s not much really to say with the install process. Having <code>iwd</code> work immediately was amazing; having to redo my partitions 3 times wasn&rsquo;t fun. But the main issue was actually this laptops&rsquo; firmware not being particularly nice with <code>GRUB</code>. The <code>--removable</code> flag solved that though after one entirely unneeded reinstall.</p>
<figure>
    <img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/byzxor/chimeraniri.webp"
       alt="Fastfetch screenshot" height="60%", width="60%">
    <figcaption>Obligatory <code>fastfetch</code></figcaption>
</figure>
<p>Then there was the next stage of getting a greeter to work. Short story: <code>greetd</code> and <code>tui-greet</code> are a wonderful combo. Installed <code>niri</code> and got my dotfiles. A few quirks dealing with the FreeBSD-like userland (this actually improved some scripts) and I got my <code>swaybg</code> and <code>swayidle</code> scripts working. Some more usual things and it&rsquo;s all good to go.</p>
<p>Yep.</p>
<p>I was hesitant about <code>dinit</code> after my time really enjoying <code>OpenRC</code>. That was silly of me. <code>dinit</code> is wonderful. I was able to setup custom services in <strong>3 lines per service</strong>. Insane.</p>
<p>I knew the userland and <code>musl</code> changes would cause <em>some</em> problems once I started trying to build some projects but it seems to only be a single OpenSSL dep doing this, so that shouldn&rsquo;t be too annoying too resolve&hellip;?</p>
<p>Unfortunately, there is one mystery problem that I remember this laptop having before, except now I can recreate it! Sometimes it will just randomly reboot and nothing shows up in the logs. <del>If I visit &lt;newsblur.com&gt; in any browser and wait 5 - 10 seconds, it will happen. I have a suspicion it&rsquo;s GPU related, but I need to validate that <em>somehow</em>. This wouldn&rsquo;t be much of a problem if Newsflash worked, but it doesn&rsquo;t which is most peculiar. I will continue trying to figure this one out because I need my RSS feeds (although I plan on moving away from Newsblur after 13 years since the slop coding is now strong there).</del> This no longer happens. I am now more perplexed</p>
<p>A final gripe with Chimera is again due to <code>musl</code> and the strictness of <code>cports</code> (these are both things I very much agree with however): I have to use Flatpak for certain things. And I don&rsquo;t like Flatpak because it is very good at wasting space. It has been a few years since I used it so maybe it&rsquo;s less ridiculous now, but we&rsquo;ll see. There&rsquo;s also a delightful bug with Niri currently where no Flatpak apps can access the clipboard or vice-versa. Having to install Bitwarden via Flatpak makes it a bit useless&hellip;</p>
<p>Overall, I like Chimera so far. It&rsquo;s making me think in yet another way but also needing to find replacements for things (hurry up and finish plz <a href="https://github.com/chimera-linux/cports/pull/5506">#5506</a>). Let&rsquo;s see what happens when I start actually developing with it. It&rsquo;s a slight shame since I wanted to move away from Niri and Waybar (ravaged by slop) on a machine I would use often before making <em>whatever</em> my replacements. Maybe I&rsquo;ll just do that in a VM instead. And then eventually I&rsquo;ll change my main PC to use Gentoo. One day.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Getting In With Gentoo</title>
      <link>https://lockeb.dev/posts/getting-in-with-gentoo/</link>
      <pubDate>Fri, 03 Apr 2026 12:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/getting-in-with-gentoo/</guid>
      <description>&lt;p&gt;This will &lt;em&gt;hopefully&lt;/em&gt; be a short series about me switching away from Arch to Gentoo. This is the &amp;lsquo;in&amp;rsquo; post: why, how, etc. Later will be the &amp;lsquo;on&amp;rsquo; post: results, regrets, positives, etc. In between there might be a &amp;rsquo;the fuck in&amp;rsquo; post where I talk about the problems getting it &amp;lsquo;onto&amp;rsquo; to my main machine, but I hope not.&#xA;Whether or not this switch is a good idea is a life question left up to the reader.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This will <em>hopefully</em> be a short series about me switching away from Arch to Gentoo. This is the &lsquo;in&rsquo; post: why, how, etc. Later will be the &lsquo;on&rsquo; post: results, regrets, positives, etc. In between there might be a &rsquo;the fuck in&rsquo; post where I talk about the problems getting it &lsquo;onto&rsquo; to my main machine, but I hope not.
Whether or not this switch is a good idea is a life question left up to the reader.</p>
<blockquote>
<p>A warning: There&rsquo;s a good chance that in the first section of this post I will state some things that appears as fact. If it doesn&rsquo;t have a source linked to it, that likely means it&rsquo;s something I have read but not saved where I read it. I read a lot of things online but don&rsquo;t save them because I never think I need to refer to them (unless I&rsquo;m doing that deliberately). If you disagree with something and have a source(s) I would be delighted to read them. This warning is basically here since having any view on <code>systemd</code>, coding LLMs, or &lsquo;fascism in OSS communities&rsquo; tends to attract unsolicited opinions</p>
</blockquote>
<hr>
<h2 id="the-story-so-far">The Story So Far&hellip;</h2>
<blockquote>
<p>🎵 carry on my wayward son 🎵</p>
</blockquote>
<p>I&rsquo;ve been an Arch Linux user for a few years now. Before that it was Debian (but as a surplus machine to a pair of MacOS &amp; Windows machines). I&rsquo;ve also mucked around with other distros over the years (putting <code>crunchbang!</code> on an EeePC is something I weirdly remember). However, due to some recent happenings, my personal views don&rsquo;t necessarily align with using Arch as my primary distro. Of course it does make some things easier (mainly gaming and updating) but here is where you will either a) stop reading, b) get angry at me or c) carry on with trepidation. I don&rsquo;t like where <code>systemd</code> is heading (or has been) for a while now. In the same week 2 things happened: they allowed LLM generated code, and they allowed that pre-age-verification-compliance code. The former is an infuriating debate that won&rsquo;t stop (you know my side at least) and I&rsquo;ll try not to dwell on it here (it will show up again though). The latter is a worrying slide away from Linux principles of what people were warning about nearly a decade ago when <code>systemd</code> somehow kept being the init system of choice for nearly every distro. People more eloquent than me have written very good pieces about this, which I unfortunately never saved to link here.</p>
<h3 id="a-visual-aside">A Visual Aside</h3>
<p>Simultaneously I have been looking for a new desktop environment. I love KDE&rsquo;s philosophies but the software just works in ways I don&rsquo;t like. This is not a new thing though, as I&rsquo;m sure the KDE/GNOME fight is with for every Linux user at one time or another. I don&rsquo;t like GNOME&rsquo;s gentle shift to LLMness (albeit that is yet to be proven). This whole thing was to be done during a full system refresh (there&rsquo;s a slight issue in my bootloader I also want to get rid of). However, during trial some DEs I ended up switching to Niri, because it does everything I want it to in the way I want. This will become important later.</p>
<h2 id="the-easy-way">The Easy Way&hellip;</h2>
<blockquote>
<p>&lsquo;Out of the fire&rsquo; if you will</p>
</blockquote>
<p>As a &lsquo;sensible&rsquo; person I did explore some alternatives with the primary goal of &lsquo;removing <code>systemd</code> from Arch&rsquo;. What exists are 2 things that I would not be happy using, and a third that just did not work.</p>
<h3 id="the-bible-failed-us-or-how-maybe-im-not-that-great">The Bible Failed Us (or how maybe I&rsquo;m not that great)</h3>
<p>The thing that did not work would have been the easiest solution, in the sense that it would have impact my daily life very little, was to rip out <code>systemd</code> from my installation and replace it with <code>OpenRC</code>. Heck, there&rsquo;s even a page on the venerable ArchWiki with instructions on how to do this.</p>
<p>It did not work, I had to revert everything, and I lost about 45 minutes of my life. I (perhaps stubbornly) decided that I would wrap this whole ordeal into a full system wipe that I&rsquo;ve been wanting to do.</p>
<blockquote>
<p>If you have successfully done this, I would be keen to hear!</p>
</blockquote>
<h3 id="so-what-does-google-say">So What Does Google Say?</h3>
<p>Artix. Even guides that say &ldquo;do not follow the ArchWiki&rdquo; recommend using Artix (or it&rsquo;s repos at the very least). Unfortunately, Artix suffers from a slight fashy issue I am told. There is no direct evidence of this I could find but core devs stating they are in the middle and accepting of anyone echoes Framework&rsquo;s &ldquo;big tent&rdquo; post (if you are unfamiliar with that, please search for it and why it was written). As I cannot vet these concerns either way, I do and will not trust it.</p>
<h3 id="so-what-does-a-different-search-engine-say">So What Does a Different Search Engine Say?</h3>
<p>ArchBang. Huh, this was new. I love a low effort developer page. I agree with a lot of what the dev does. Unfortunately on check the repo I was hit with the Github slop warning<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. Checked for the usual suspects and <em>sigh</em>. Re-read some of the devs posts. They&rsquo;re not quite full in with the LLM-do-everything-crowd but they use it more than I&rsquo;m comfortable with. I back this up with that this is also a very hobbyist distro and not a daily-driver.</p>
<p>Ahh shit</p>
<h2 id="the-hard-way">The Hard Way</h2>
<blockquote>
<p>&lsquo;And into the frying pan&rsquo;</p>
</blockquote>
<p>I spend a bit of time on the &ldquo;anti-LLM&rdquo; side of the internet a.k.a Mastodon and sometimes I find an interesting post leading to an interesting source of information. This particular one brought to my attention that a few distros had taken strong stances on LLM code, that is outright refusing it. Of interest to me were Gentoo (obviously) and Chimera. Chimera scratches a load of certain itches but it doesn&rsquo;t look too friendly with one of my daily-driver requirements: gaming. And so Gentoo entered the &ldquo;maybe I should really do this&rdquo; discussions in my head. I have little experience with Gentoo-running folk, except for that once guy I was friends with back in uni who spend the whole day compiling Gentoo on his laptop and had to sit in awkward places around campus (2010 was a <em>simpler</em> time). But also why are these 2 of interest to me? Well they don&rsquo;t use <code>systemd</code>. Gentoo defaults to <code>OpenRC</code> (but does offer easy methods to use <code>systemd</code>), while Chimera uses <code>dinit</code>.</p>
<p>Welp then, Gentoo it is. For those unfamiliar, Gentoo has quite the reputation for being &lsquo;difficult&rsquo;. This is due to the fact you &lsquo;basically&rsquo; configure it from scratch. And since I&rsquo;m a paranoid person that doesn&rsquo;t want to be without a primary PC for a while, I thought I&rsquo;d try it out in QEmu first.</p>
<h2 id="quizzical-emu-wrong-on-both-counts">Quizzical Emu (wrong on both counts)</h2>
<p>The Gentoo community is quite nice it seems as the Handbook for AMD64 is pretty good. As long as you actually follow it. Full disclosure: I use <code>virt-manager</code> to help with QEmu stuff, which is a bit of a double-edged sword. My goal here is to get Gentoo booting into Niri and get some services designed for <code>systemd</code> running.</p>
<h3 id="attempt-1">Attempt 1</h3>
<p>Following the Handbook is easy, just a lot of typing. Foolishly decided to use the <code>dist-kernel</code> and about an hour in (while I&rsquo;m in another room) I run out of disk space.</p>
<ul>
<li>Lesson 1: more disk space</li>
</ul>
<h3 id="attempt-2">Attempt 2</h3>
<p>Ok, VM drive now has 3 times the space. Find a comment saying &ldquo;for your first Gentoo install maybe use the <code>dist-kernel-bin</code> to save on time&rdquo;. Good advice. All is going well until setting up GRUB and I get a load of weird <code>EFI</code> related warnings. Oh right, I guess I need to use non-EFI boot drive for QEMU. That makes sense. This attempt was also hampered by me fucking up the <code>USE</code> flags for <code>installkernel</code> THREE separate times.</p>
<ul>
<li>Lesson 2: actually know what the system is compatible with</li>
<li>Lesson 3: Measure twice, cut once</li>
</ul>
<blockquote>
<p>There was an attempt 2.5 where I restored a snapshot and tried again but I forgot to <code>emerge sys-kernel/installkernel</code> after setting the <code>dracut</code> USE flag. Oops</p>
</blockquote>
<h3 id="attempt-3">Attempt 3</h3>
<p>Get all the way through and Gentoo boots! Big relief (I enjoy an easter egg as a celebration). Now to install Niri. Following the Gentoo wiki this is easy. I execute <code>dbus-run-session niri --session</code> and everything halts.</p>
<p>My inexperience with QEmu and lots of things now becomes a problem here. First thought is that maybe this VNC viewer isn&rsquo;t capable of handling graphics. So I try configuring the display to <code>Virtio</code> with no 3D acceleration. Same result. This time I enable 3D acceleration and get greeted with an error saying I need to configure a GL backend. Fair enough, but in <code>virt-manager</code> this isn&rsquo;t possible, it needs a command-line option. Eventually I find that <code>/var/log/libvirt/qmeu/NAME_OF_VM.log</code> stores the <code>qemu</code> command that <code>virt-manager</code> called. Try it out with the suggested fix and still nothing. Now begins the digging. I find a lot of stuff about <code>libvirt</code> and QEmu and OpenGL having myriad issues with myriad causes. Eventually I track down a similar problem on a <a href="https://github.com/virt-manager/virt-manager/issues/938">Github issue</a> for <code>libvirt</code>. Ultimately this works (there is some stupidity that I do applying this fix that makes it take longer than it should).</p>
<p>And now I have Gentoo running Niri in QEmu!</p>
<center>
<figure>
    <img src="https://i.ibb.co/5hq61LTr/asd.png"
       alt="Obligatory Fastfetch showing I'm *really* running Niri on Gentoo inside QEmu" height="60%", width="60%">
    <figcaption>Obligatory Fastfetch showing I'm *really* running Niri on Gentoo inside QEmu</figcaption>
</figure>
</center>
<h2 id="fun-times-ahead">Fun Times Ahead*</h2>
<p>Now I need to see if I can get some other things behaving nicely, specifically SDDM, a daemon I use, <code>doas</code> and maybe a couple of other things. I would also maybe test Steam but that&rsquo;s definitely pushing the limits here. I also want to try building and managing a tool from source that has no Gentoo flavour.</p>
<p>I had technically set <code>doas</code> up during the install phase but with a very annoying config:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>permit :wheel</span></span></code></pre></div><p>I would rather like it to behave like how <code>sudo</code> defaults: 2 retries, remember rights for 5 minutes. Well the retry prompt doesn&rsquo;t seem to exist but persistence does:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span>permit persist :wheel</span></span></code></pre></div><p>Nice.</p>
<blockquote>
<p>Why <code>doas</code>? I&rsquo;ve heard good things about it (and also <code>capsudo</code>) so I thought I&rsquo;d try it out</p>
</blockquote>
<p>SDDM was also easy thanks to the <a href="https://wiki.gentoo.org/wiki/SDDM">docs</a> (yet again). Tiny Niri issue but not a big deal. Now for the first daemon: <code>jottad</code>. I use <code>Jottacloud</code> as my Dropbox-replacement. As much as I have minor issues with it, it&rsquo;s pretty good and the companies overall mission is good (except the lack of OSS but that&rsquo;s pretty normal with cloud storage companies).</p>
<h3 id="jottad"><code>jottad</code></h3>
<p>This is a little more involved. Firstly, you need to get the <code>bin</code>s from their <a href="https://repo.jotta.us/archives/">site</a>. The tarball actually contains some default config and basic docs, which was very unexpected. However, it&rsquo;s built around <code>systemd</code>. So that means writing an <code>OpenRC</code> script, which is weirdly tiny.</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span>command<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/usr/bin/jottad&#34;</span>
</span></span><span style="display:flex;"><span>pidfile<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/run/</span><span style="color:#e6db74">${</span>RC_SVCNAME<span style="color:#e6db74">}</span><span style="color:#e6db74">.pid&#34;</span></span></span></code></pre></div><p>After moving the bins to <code>/usr/bin</code> and the default config to <code>/etc/jottad/</code>, <code>rc-service start jottad</code> does&hellip;nothing. No logs. Just nothing.</p>
<p>Reading some docs I find this line from the OpenRC <a href="https://github.com/OpenRC/openrc/blob/master/service-script-guide.md">Service Script Writing Guide</a>:</p>
<blockquote>
<p>The interpreter for service scripts is #!/sbin/openrc-run. Not using this interpreter will break the use of dependencies and is not supported</p>
</blockquote>
<p>Oops. I switch to that and I&rsquo;m greeted with <code>* WARNING: jottad is already starting</code> but nothing actually happens. A quick search for this and I end up back on the Gentoo <a href="https://wiki.gentoo.org/wiki/OpenRC/Prefix#XXX_is_already_starting">OpenRC page</a>. I just need to run <code>openrc</code> to see what&rsquo;s going wrong, which seems to be <code>start-stop-daemon: --stdout and --stderr are only relevant with --background</code>. Straightforward I guess. I add the line anddd it starts! So the complete script is as follows (extra notes in comments):</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/sbin/openrc-run
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>depend<span style="color:#f92672">()</span> <span style="color:#f92672">{</span>
</span></span><span style="display:flex;"><span>  need net <span style="color:#75715e"># jottad needs to look at 127.0.0.1, I didn&#39;t try 0.0.0.0 that would make this not needed</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">}</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>command<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/usr/bin/jottad&#34;</span>
</span></span><span style="display:flex;"><span>pidfile<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/run/</span><span style="color:#e6db74">${</span>RC_SVCNAME<span style="color:#e6db74">}</span><span style="color:#e6db74">.pid&#34;</span>
</span></span><span style="display:flex;"><span>command_args<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;stdoutlog&#34;</span>                <span style="color:#75715e"># tell jottad to use stdout for logs</span>
</span></span><span style="display:flex;"><span>output_log<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/var/log/</span><span style="color:#e6db74">${</span>RC_SVCNAME<span style="color:#e6db74">}</span><span style="color:#e6db74">.log&#34;</span> <span style="color:#75715e"># need to put logs somewhere</span>
</span></span><span style="display:flex;"><span>error_log<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;/var/log/</span><span style="color:#e6db74">${</span>RC_SVCNAME<span style="color:#e6db74">}</span><span style="color:#e6db74">.err&#34;</span>  <span style="color:#75715e"># need to put errors somewhere</span>
</span></span><span style="display:flex;"><span>command_background<span style="color:#f92672">=</span>true                 <span style="color:#75715e"># from error message above</span>
</span></span><span style="display:flex;"><span>command_user<span style="color:#f92672">=</span><span style="color:#e6db74">&#34;root:jottad&#34;</span>              <span style="color:#75715e"># uhh this might be wrong but I&#39;ll deal with that later</span></span></span></code></pre></div><p>Unfortunately I now need a way to handle updates. That will come later once I&rsquo;m fully Gentoo&rsquo;d (that sounds gross).</p>
<p>To test <code>jottad</code> I kinda need to install a browser (Jottacloud uses token auth and copy/paste in QEmu ain&rsquo;t there), and since I&rsquo;ll be doing that anyway I might as well and install <code>Librewolf</code> (but the <code>bin</code> version, I don&rsquo;t feel like waiting for several hours). But first&hellip;</p>
<h3 id="fuzzel"><code>fuzzel</code></h3>
<p>Let&rsquo;s get some more of my &rsquo;normal&rsquo; functions going here. I use <code>fuzzel</code> as my launcher because I ran into a lot of issues with the other one I was using (that I forget the name of) and I just decided &ldquo;simple is best&rdquo;. And here is where I learned about &ldquo;unmasking&rdquo;. Conceptually it makes sense, but practically it would be really nice if there was an easy way to see why and when a package was masked. The <a href="https://wiki.gentoo.org/wiki/Knowledge_Base:Unmasking_a_package">wiki</a> to the rescue.</p>
<h3 id="librewolf"><code>Librewolf</code></h3>
<p>Man, that Gentoo wiki really is something. It&rsquo;d be better than the ArchWiki iff more people used Gentoo I think. Anyway the <a href="https://wiki.gentoo.org/wiki/LibreWolf">Librewolf page</a> is pretty good. And it works.</p>
<p>Running out of things tricky to test now. Everything else I use is pretty standard, except maybe my dotfile management.</p>
<h3 id="chezmoi"><code>chezmoi</code></h3>
<p>Oh, it&rsquo;s in <a href="https://wiki.gentoo.org/wiki/Project:GURU">Guru</a>. No biggy. Easy. I guess this didn&rsquo;t deserve it&rsquo;s own section.</p>
<h3 id="steam">Steam</h3>
<blockquote>
<p>From the steamed hams</p>
</blockquote>
<p>Again, the <a href="https://wiki.gentoo.org/wiki/Steam">wiki entry</a> steps in clutch with it&rsquo;s slightly-poorly-worded paragraph about &lsquo;pure Wayland systems with a global <code>-X</code> flag&rsquo; (guess what I did). Alas, <code>emerge</code> still blocks me due to <code>dbus</code> having it&rsquo;s <code>ABI_X86</code> flag set to <code>64</code>. A quick search to validate if I was correct and I was halfway right. Instead of setting the <code>ABI_X86</code> <code>USE</code>, I just needed to <em>sigh</em> enable the <code>X</code> <code>USE</code> flag for it. Now I can install <code>steam-launcher</code>&hellip;</p>
<p>&hellip;Why is it compiling <code>llvm</code>?&hellip; This was the only surprising thing to happen and it&rsquo;s because I didn&rsquo;t actually check what was being pulled in.</p>
<p>4 episodes of One Piece later and we&rsquo;re done. Well, after a restart really. I&rsquo;m not going to try and get WINE or Proton working just here, because a) it will take a while and b) testing it will be a bit of a pain. But I can do something&hellip;</p>
<center>
<figure>
    <img src="https://i.ibb.co/svTYppYR/factorio-qemu-small.png"
       alt="It's Factorio on Gentoo in QEmu!" height="60%", width="60%">
    <figcaption>You know, I could be starting a new save instead of all *this*...</figcaption>
</figure>
</center>
<p>I think that&rsquo;s that then&hellip;</p>
<h2 id="conclusion">Conclusion</h2>
<p>Am I ready to make this on my main PC? Maybe still with the <code>dist-kernel</code>. But in that case maybe I should practice with the source kernel in QEmu (albeit that will take many hours to compile). I do have an unused laptop (&ldquo;unused&rdquo; meaning it has Proxmox on it but it&rsquo;s been dormant for a couple of months) that would make a great weekend project and a real testbed (i.e. test full functionality by plugging it into my setup and using it for a couple of hours/days).</p>
<p>The setting up of various <code>USE</code> flags and licenses etc. is really cool, BUT bringing a system back to working after a catastrophic failure would be no mean feat. I&rsquo;m not really sure what the best approach to backing up and restoring alllll those files would be. I think that before I start the full system wipe, I need to resolve that. And also investigate some sort of &lsquo;rollback&rsquo; management. The ability to completely break your system by accident is <em>high</em>. This scares me a bit, mainly because I don&rsquo;t want to spend 5+ hours setting things up from scratch if I fuck something up. And well I totally forgot about when the <code>profile</code> updates. That I have no idea about. I just need to pay attention to the <code>eselect news list</code> outputs.</p>
<p>As I alluded to back at the start of this, I&rsquo;m also in the middle of changing my display environment and entire workflow (this includes switching to vertical tabs and still migrating to <code>helix</code> from <code>vim</code>). There are still some things that need to worked on there, but most of those things are effectively trivial. This is the first time in 16 years I&rsquo;ve done without a &lsquo;Quake-style&rsquo; terminal and that takes a bit of work to undo. I still also have a bunch of other things I need to do, such as restoring my web services.</p>
<p>If, somehow, you&rsquo;ve made it this far and are also curious about trialling Gentoo: do it! Maybe just use this post as inspiration and not a source of truth.</p>
<h3 id="some-other-miscellaneous-learnings">Some Other Miscellaneous Learnings</h3>
<ol>
<li>Mirrors can sometimes be borked. I need to see if there&rsquo;s a way to reduce the timeout. I wish there was a mirror-ranking system that could be done once a week or even daily. Maybe I need to use the <code>rsync</code> versions instead</li>
<li>Searching for packages can be a bit of mess, perhaps there&rsquo;s a way to make this easier&hellip;</li>
<li>There is a lot more manual work than I anticipated, but mostly coming from other places (see package management). It&rsquo;s interesting, there&rsquo;s some really easy solutions you could do but they would take away from the spirit of Gentoo. I just wish the some more critical information was more readily available</li>
<li>Setting up packages take a lot longer than you expect, even when everything is working properly. Find some other things to do while you wait</li>
</ol>
<p>I&rsquo;m sure I learned some other things while doing this (I know I did) but I think these are the main things to consider when switching to Gentoo. It&rsquo;s not the groundbreaking learning experience I&rsquo;ve seen people say online, but it&rsquo;s certainly not a passive experience.</p>
<hr>
<p>This was mostly written while having Soulless&rsquo;s &ldquo;Shiny In Purity&rdquo; on repeat. Cracking album, give it a spin</p>
<iframe style="border: 0; width: 100%; height: 42px;" src="https://bandcamp.com/EmbeddedPlayer/album=1309433172/size=small/bgcol=333333/linkcol=0f91ff/transparent=true/" seamless><a href="https://soullessdsbm.bandcamp.com/album/shine-in-purity">Shine in Purity by Soulless</a></iframe>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>On your Github account go and block Claude and other LLM accounts.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>The mono(repo) is tidy</title>
      <link>https://lockeb.dev/posts/the-monorepo-is-tidy/</link>
      <pubDate>Sun, 07 Dec 2025 16:30:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/the-monorepo-is-tidy/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m cleaning up all my stray repositories and placing them into more sensible mono-repos. This is mainly to make my life easier when wanting to work on something random. The current structure looks a bit like:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;All ongoing projects under one repo&lt;/li&gt;&#xA;&lt;li&gt;All homelabbing stuff is split into 2: one public, one private (secrets are still handled &lt;em&gt;properly&lt;/em&gt;)&lt;/li&gt;&#xA;&lt;li&gt;One for my writing and knowledge-acquisition&lt;/li&gt;&#xA;&lt;li&gt;&lt;code&gt;pages&lt;/code&gt; (this is new and will serve a purpose later)&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;This is a fairly boring process by hand, and that is why &lt;code&gt;bash&lt;/code&gt; exists! Here&amp;rsquo;s the script I used to dump whole repos into subdirs in a new repo, while preserving all their history. This is extra beneficial if the project becomes good enough to warrant going back into its own repo. This script is actually pretty straight forward but is *nix only, thanks to the &lt;code&gt;xargs&lt;/code&gt;. You can probably use &lt;code&gt;git filter-repo&lt;/code&gt; but I wanted a result quickly and someone on SO had such as nixxy solution.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I&rsquo;m cleaning up all my stray repositories and placing them into more sensible mono-repos. This is mainly to make my life easier when wanting to work on something random. The current structure looks a bit like:</p>
<ul>
<li>All ongoing projects under one repo</li>
<li>All homelabbing stuff is split into 2: one public, one private (secrets are still handled <em>properly</em>)</li>
<li>One for my writing and knowledge-acquisition</li>
<li><code>pages</code> (this is new and will serve a purpose later)</li>
</ul>
<p>This is a fairly boring process by hand, and that is why <code>bash</code> exists! Here&rsquo;s the script I used to dump whole repos into subdirs in a new repo, while preserving all their history. This is extra beneficial if the project becomes good enough to warrant going back into its own repo. This script is actually pretty straight forward but is *nix only, thanks to the <code>xargs</code>. You can probably use <code>git filter-repo</code> but I wanted a result quickly and someone on SO had such as nixxy solution.</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span><span style="color:#75715e">#!/bin/bash
</span></span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>REPO<span style="color:#f92672">=</span>$1
</span></span><span style="display:flex;"><span>REPOMIG<span style="color:#f92672">=</span>$REPO<span style="color:#e6db74">&#34;migration&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>git remote add $REPO ssh://git@codeberg.org/<span style="color:#f92672">{</span>YOUR_USERNAME<span style="color:#f92672">}</span>/$REPO.git
</span></span><span style="display:flex;"><span>git fetch $REPO
</span></span><span style="display:flex;"><span>git branch $REPOMIG $REPO/main
</span></span><span style="display:flex;"><span>git checkout $REPOMIG
</span></span><span style="display:flex;"><span>mkdir $REPO
</span></span><span style="display:flex;"><span>git ls-tree -z --name-only HEAD | xargs -0 -I <span style="color:#f92672">{}</span> git mv <span style="color:#f92672">{}</span> $REPO
</span></span><span style="display:flex;"><span>git commit -m <span style="color:#e6db74">&#34;migrated </span>$REPO<span style="color:#e6db74"> to </span>$REPO<span style="color:#e6db74">/&#34;</span>
</span></span><span style="display:flex;"><span>git checkout main
</span></span><span style="display:flex;"><span>git merge --allow-unrelated-histories -m <span style="color:#e6db74">&#34;Assimilated </span>$REPO<span style="color:#e6db74">&#34;</span> $REPOMIG 
</span></span><span style="display:flex;"><span>git push -u origin main
</span></span><span style="display:flex;"><span>git remote rm $REPO</span></span></code></pre></div><p>Now I just need to make a script that does the opposite (although I don&rsquo;t actually know when that would come in handy).</p>
<hr>
<p>Apologies if you&rsquo;re in dark mode and the codefence is blinding you. My CSS appears to no longer be working, but that&rsquo;s what I get for not checking this blog for 10 months.</p>
]]></content:encoded>
    </item>
    <item>
      <title>I have a Voyager and I must Type</title>
      <link>https://lockeb.dev/posts/i-have-a-voyager-and-i-must-type/</link>
      <pubDate>Sat, 22 Mar 2025 10:28:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/i-have-a-voyager-and-i-must-type/</guid>
      <description>&lt;p&gt;ZSA: Did they really name themselves in such a way just to cause havoc for large handed QWERTY users on their keyboards?!?&lt;/p&gt;&#xA;&lt;p&gt;So I finally did it. I bought a ZSA Voyager. And also a shit load of keyswitches. Let&amp;rsquo;s get the big question out of the way first: do I like it? Yes, but&amp;hellip; It&amp;rsquo;s a great keyboard, even if my comparison points are not very mechanical. The &amp;lsquo;but&amp;rsquo; though does a LOT of heavy lifting. But let&amp;rsquo;s start with the &amp;lsquo;why&amp;rsquo;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>ZSA: Did they really name themselves in such a way just to cause havoc for large handed QWERTY users on their keyboards?!?</p>
<p>So I finally did it. I bought a ZSA Voyager. And also a shit load of keyswitches. Let&rsquo;s get the big question out of the way first: do I like it? Yes, but&hellip; It&rsquo;s a great keyboard, even if my comparison points are not very mechanical. The &lsquo;but&rsquo; though does a LOT of heavy lifting. But let&rsquo;s start with the &lsquo;why&rsquo;.</p>
<p>In previous posts I&rsquo;ve talked about wanting a split keyboard that helps my back (yes unlike most people I see, my main issue is posture and not wrist/finger pain). I am a large individual and hunching over all day everyday isn&rsquo;t great. Also I&rsquo;ve just wanted a split ergo keyboard that looks cool. On these fronts, it&rsquo;s a success. And really I just like <em>things</em> that are functional, so maybe that was all the motivation I needed all along.</p>
<p>But now the bad. There&rsquo;s 2 aspects here. The first is about relearning how to touch type and things of that ilk. The second is about the board itself.</p>
<h3 id="the-mavis-beacons-are-lit">The (Mavis) Beacons are lit!</h3>
<p>Eons ago (years that start with 19 and a few beyond that) I had typing classes. Really. Some of these were at school, some my mum signed me up for (I started having to use a laptop at school in 1998/year 5 because dyslexia and dysgraphia and needing to type at a reasonable pace was required), but they never really got embedded. Sure I know the basics of it but like most people I developed my own style over time because it was easy and fast enough. I really wish now that I had actually stuck with it properly because that would have probably saved a lot of time (literally) over the years, but also now would prevent this post from existing. Because holy shit, I am fucking slow now that I have to use a new form-factor of keyboard with a new layout of keycaps.</p>
<p>Of course I didn&rsquo;t go into this journey blind, I watched and read quite a few things to help me decide. Hell, like three days before buying this I almost bought the Dygma Raise 2, and thank fuck I didn&rsquo;t (more in the board section). One thing that no-one seemed to cover was the absolute mental block that happens when having to relearn typing. Everyone talks about how it&rsquo;ll be slow and painful and slow, but this mental block is THE hardest thing. Specifically, having to kinda think about where your fingers should go to press what symbol, especially if its on another layer, not only disrupts my typing but actively discourages me from doing things. For example, I had to migrate a lot of code at work (re-monolithing a service for reasons) and I kinda did it half arsed because having to fix and type things just elicited some level of anxiety in me. It&rsquo;s also in my personal projects, which being in Rust sure requires a LOT of typing. However, I am stubborn. So I power through because I want to master this thing, and not have another thing put into a box stored in the shelves behind me.</p>
<p>And yes, this entire time I&rsquo;m sticking with QWERTY for the simple fact I need to use other keyboards at times (in both US QWERTY and Nordic ISO forms). Maybe when I master this I&rsquo;ll explore Colemak-DH or Graphite for some real fun and speed and not having my right little finger be a jerk (after months of pain). Although sticking with QWERTY has allowed some bad habits to stick around like &ldquo;pressing K with right little finger&rdquo; and &ldquo;pressing A with the left middle&rdquo; but they should go away after some time&hellip;</p>
<p>An extension to all this is that the Voyager has only 52 keys. That means layers and programming it the way that works best for me. I&rsquo;m <em>still</em> figuring out whats best but right now it&rsquo;s not too different from the default, but I&rsquo;m still working on it (where space and backspace + delete are is a constant source of frustration for my fingers). Speaking of the board&hellip;</p>
<h3 id="taking-a-trip">Taking a trip</h3>
<p>(Voyager, get it?)</p>
<p>I opted for the Pro Red keyswitches because I read somewhere they were the quietest. I don&rsquo;t know what scale those people operate on but they sure as hell weren&rsquo;t. They were deafening. Thankfully a post tipped me off to some very quiet switches called &ldquo;Ambient Nocturnals&rdquo;. From what I had read about these, they are practically silent but very lightweight. Mechboards had a heap of those in stock, but also the slightly heavier &lsquo;Twilight&rsquo;s. I bought 5 sets of each (fucking spenno I know) and I was so glad I did, because it turns out they are indeed silent. And also the Nocturnals are indeed slightly too light for me. However some of the Twilghts died in transit (3 actually) so I have a few Nocturnals in here and it&rsquo;s actually noticeable. BUT the important thing is that it&rsquo;s almost as quiet as my Logitech MX Keys S, which is amazing and I don&rsquo;t cringe at every keypress now.</p>
<p>Above I mentioned I was a large individual, and that corresponds to my hands as well. A reduced key, low-profile, small-footprint board <em>should</em> have given me some hints about this but the Voyager is small. That has been quite a challenge. Have a picture to show my concerns.</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/byzxor/52ediot-1.webp" alt="2025-03-22 11"></p>
<p>However, it&rsquo;s been useful to my left thumb which is slightly smaller than it should be due to an accident when I was 10. There&rsquo;s not much I can do about this apart from getting used to it, which is slowly happening.</p>
<p>One main complaint I have with this though is how I wish for a third thumb key. That would make so many things just that bit easier, but I can see why they stuck with two. Okay, one more complaint was that I wish it could store profiles. I jump between Linux (daily personal), Mac (work), and Windows (gaming I guess) frequently. I guess a solution is for one system to have the &rsquo;true&rsquo; layout and then use layout software on the others to line things up. Basically this is just an ALT, CTRL, Meta/CMD problem. I&rsquo;m sure that someone out there has figured it out&hellip;</p>
<h3 id="onwards">Onwards</h3>
<p>It&rsquo;s only been a week with this, so there&rsquo;s still a lot more work to go. I have only switched to my MX Keys once and that was out of a need to do something quickly. The main thing I have been changing around is my trackball. I&rsquo;m <em>still</em> getting used to that, but during this week I have mainly used my mouse because I needed something to be normal and fast. I am now back to trackballing and it&rsquo;s fine. Just gotta learn and get used to it all. I of course have been spending a bunch of time with monkeytype doing long stretches of english and moderate bursts of Rust for symbol training.</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/byzxor/05edit.webp" alt="That ergo drug sure is a trip"></p>
<p>Just gotta keep voyaging (ick I know).</p>
]]></content:encoded>
    </item>
    <item>
      <title>Parsing and enriching Clockify data for fun?</title>
      <link>https://lockeb.dev/posts/parsing-and-enriching-clockify-data-for-fun/</link>
      <pubDate>Wed, 19 Feb 2025 03:47:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/parsing-and-enriching-clockify-data-for-fun/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve been interested in my working habits for a few years now. Well, maybe more than a few. Historically, I&amp;rsquo;ve been the type of person who will work for 9 - 10 hours a day. This was likely ingrained from an early age since my dad routinely works that (if not longer) and has been for 40 years. In late 2021 a colleague clued me into Clockify: a work time tracking tool. It&amp;rsquo;s mostly geared towards people who need to bill clients per hour, but it functions well enough to track and store usual working hours. Unfortunately, all the juicy stuff is pay-walled away, but that wouldn&amp;rsquo;t be enough for me anyway.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve been interested in my working habits for a few years now. Well, maybe more than a few. Historically, I&rsquo;ve been the type of person who will work for 9 - 10 hours a day. This was likely ingrained from an early age since my dad routinely works that (if not longer) and has been for 40 years. In late 2021 a colleague clued me into Clockify: a work time tracking tool. It&rsquo;s mostly geared towards people who need to bill clients per hour, but it functions well enough to track and store usual working hours. Unfortunately, all the juicy stuff is pay-walled away, but that wouldn&rsquo;t be enough for me anyway.</p>
<p>As such, &lsquo;Locke&rsquo;s Stupid Clockify Analyser&rsquo;(<code>LSCA</code>) was born. My initial goal was simple: get all my Clockify data and plot it against various things. Getting to that point was easily achievable via a spreadsheet, so it needed more. I have no idea where the following came from, but at some point I thought correlating my working time with various weather would be interesting.</p>
<p>After probably around 10 - 12 hours of coding I came to a natural conclusion point with this project, so now I&rsquo;ll explain it a bit in depth then go through the results.</p>
<h2 id="lsca">LSCA</h2>
<p>LSCA can be split into two parts: data wrangler and plotter. The data wrangler does the following:</p>
<ol>
<li>Imports a Clockify CSV export</li>
<li>Flattens the entries into single days</li>
<li>Gets weather information for that day at my lat/lon</li>
<li>Store it in an SQlite DB</li>
</ol>
<p>Pretty simple. The weather data is all from &lt;open-meteo.com&gt; which fucking rocks.</p>
<p>The plotter is where most of the coding time went. I&rsquo;ll explain shortly, but this basically does what it sounds like:</p>
<ol>
<li>Run some SQL query</li>
<li>Do some data post-processing</li>
<li>Draw some plots</li>
</ol>
<p>And if you thought I did this in some sensible language for doing this type of stuff, you&rsquo;d be wrong since I used Go. Why? I wanted to do something small (and finish it) in Go because I&rsquo;ve been using it more and more at work (and this project actually really helped with that).</p>
<h3 id="components">Components</h3>
<ul>
<li>For the queries I used <code>go-resty</code>, which I&rsquo;m very familiar with. However, I tried using <code>v3</code> but it refused to behave, so I went back to the comfortable <code>v2</code></li>
<li>For the CSV parsing I used <code>gocsv</code> because I can directly unmarshal a file into an struct type with little pain. Big recommend</li>
<li>For the SQLite stuff I used <code>go-sqlite3</code> which is fine. It requires <code>CGOENABLED</code> at compile time which I don&rsquo;t particularly like, but it works and doesn&rsquo;t shove any ORM in my face (which funnily enough could have been useful)</li>
<li>For plotting I used <code>gonum</code>&rsquo;s <code>plot</code> package. It&rsquo;s fine. Kinda. I does sort of a job sort of well, but it&rsquo;s clearly not built as a total <code>matplotlib</code> replacement</li>
</ul>
<h3 id="the-feature-creep">The Feature Creep</h3>
<p>At some point, prior to writing the plotting code, I planned out a way for this tool to be bigger and better and eventually enough that it would be running on my homelab (still in progress) so I could update it at anytime. Once the plotting began, it was very clear that these new goals couldn&rsquo;t be achieved. Additionally, once I started seeing some of the results, I realised that updating it all the time wasn&rsquo;t particularly valuable.</p>
<p>And the feature creep went away. Possibly to return at a later date, but likely not.</p>
<h2 id="results">Results</h2>
<p>The whole purpose of this project was basically for this section, so strap in. I picked a few queries that I thought to help elucidate my working habits and maybe show them in a new light. This &ldquo;few&rdquo; ultimately turned out to be six, since things like max working time per year&rsquo; is boring, while queries that utilise 5+ dimensions were not suitable (again, I&rsquo;ll explain later).</p>
<p>This data consists of 3 complete years of tracked data with 833 working days. A couple of interesting analyses had to be thrown out from the start since they were too hard to separate from noise. These are things like &ldquo;how often would I return after a headache and for how long&rdquo; or &ldquo;how did a public holiday affect my work week&rdquo;.</p>
<p>Firstly, lets look at the average working time per weekday.</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/byzxor/averageworkingtimeperweekday.webp" alt="AverageWorkingTimePerWeekday"></p>
<p>It&rsquo;s not very interesting BUT it contradicts my thoughts. Monday through Thursday I basically work just over 8 hours a day. How novel. Friday&rsquo;s I uhhh kick off a bit early, but not too early. I was surprised at how both how not much over 8 hours the four days are but also how practically identical they are. Internally, I feel that Monday and Thursday are my longest working days. This says otherwise, kinda.</p>
<p>Secondly, let&rsquo;s expand this a bit and see how it looks per the three years of data I have.</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/byzxor/meandurationperdayofweekperyear.webp" alt="MeanDurationPerDayofWeekPerYear"></p>
<p>My Mondays and Wednesdays across the 3 years are basically the same. Tuesday and Thursdays differ a little more but only by a few minutes. I do not know why my Tuesdays in 2023 were so much longer but whatever. Friday&rsquo;s on the other hand. In 2022, I would stop on average just under 7 hours of work (6.8). The rise by an hour in 2024 makes sense as the number of responsibilities I had increased dramatically (and there were quite a lot of 15-1600 meetings due to timezone differences).</p>
<p>Between these two charts, it appears that I work basically the amount of time I&rsquo;m paid for (plus a little more). Huh.</p>
<p>Thirdly, and still thinking of working time, let&rsquo;s look at how the weather affects my working time.</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/byzxor/averageworkingtimeperweathertype.webp" alt="AverageWorkingTimePerWeatherType"></p>
<p>&ldquo;Rain rain go away, come again another day&rdquo; seems to an adage that would work here. Except for when it&rsquo;s heavy. The most confusing one here is &lsquo;partly cloudy&rsquo; but I suspect that is due to only 2.9% of entries sharing that weather code. But basically aside from those rainy days, it&rsquo;s always roughly 8 hours a day. Yawn.</p>
<p>Ok, now lets look at some starting and finishing times. Things are a little more interesting but thanks to a couple of outliers, the results are very boring. Starting with the earliest time I started work per week day per year.</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/byzxor/earliest.webp" alt="Earliest"></p>
<p>I should really take out anything before 6am as those entries are insomnia driven. But if you squint real hard you can see a trend that during the course of the week I start earlier and earlier. What about the latest time I started work per week day per year?</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/byzxor/latest.webp" alt="Latest"></p>
<p>Some more outliers that could have been scrubbed (or maybe plotted in a much different way), but it&rsquo;s not very informative either way. But at least there are not 2200+ ending times. I will say though in 2022 I was much stricter about my working habits. Seems like I&rsquo;ve just given up since (again LOTS more responsibilities).</p>
<p>In hindsight, these as line graphs is just wrong and I should have used something wayy more appropriate.</p>
<p>Finally, we come to the noise graph that I was hoping would show something at least a bit interesting. This is working duration and daylight duration per year.</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/byzxor/daylight.webp" alt="Daylight"></p>
<p>Absolutely ZERO correlation. Again, if you squint you MIGHT see a slight dip during summer (oh I wonder why) but ultimately the amount of daylight in a day doesn&rsquo;t really affect my working habits.</p>
<p>What&rsquo;s the big takeaway from all these charts? I work enough, maybe a tiny bit too much. The weather and sun doesn&rsquo;t affect it, and sometimes I&rsquo;ll push hard to get things done. These conclusions I basically already knew, albeit I don&rsquo;t work as long as I thought I did.</p>
<h2 id="post-mortem">Post-Mortem</h2>
<p>The absolute main thing from this project was: use the right tool for the right job. Everything up until plotting made sense. Trying to make interesting and informative plots in Go is not easy. It might also be not possible for the data I have. But I don&rsquo;t want to spend more time trying to find out. Were I to do this project again (or maybe when I revisit this in January 2026) I would do all the analysis in Python, because doing that stuff there is dead simple and the range of tools available for you is just astounding. Gonum&rsquo;s plot is a great package and the work put in for it is amazing, but it&rsquo;s for a very specific need that just wasn&rsquo;t mine.</p>
<p>My coming to the conclusion of this project was basically due to the awkwardness in plotting. I did leave out one query I thought was interesting, namely &ldquo;after an extended break, how long did it take to return working at full capacity&rdquo; but after thinking how to do it in what I had built was just a non-starter.</p>
<h3 id="what-did-i-learn">What Did I Learn?</h3>
<ul>
<li>More Golang stuff. Generics are much more painful in Go than I thought
<ul>
<li>Structuring a Golang project</li>
</ul>
</li>
<li>Dealing with well documented public APIs. I don&rsquo;t get to do that with work (they aren&rsquo;t well documented)</li>
<li>WMO codes are kinda cool but my god what a messy standard</li>
<li>I&rsquo;m still bad a choosing the right plot for the right data. I can partially blame gonum for that I guess but still</li>
<li>USE THE RIGHT TOOL FOR THE RIGHT JOB!</li>
</ul>
<p>If you&rsquo;re interested the code is <a href="https://codeberg.org/birlocke/lsca">here</a>. It&rsquo;s not that great but it might be of interest.</p>
]]></content:encoded>
    </item>
    <item>
      <title>getting scrivener to behave on linux (really easily)</title>
      <link>https://lockeb.dev/posts/getting-scrivener-to-behave-on-linux-really-easily/</link>
      <pubDate>Wed, 15 Jan 2025 16:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/getting-scrivener-to-behave-on-linux-really-easily/</guid>
      <description>&lt;p&gt;Currently back in Linux land (arch btw) as my daily driver, and I felt like getting some writing going. I use Scrivener for my longer things (albeit I have long considered switching to something else but the options are endless &amp;amp; all have shortcomings). Unfortunately, it doesn&amp;rsquo;t have a Linux port. As such, WINE to the rescue. But considering I have a bunch of Windows games already on this machine, maybe I could use one of those tools to get Scrivener running.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Currently back in Linux land (arch btw) as my daily driver, and I felt like getting some writing going. I use Scrivener for my longer things (albeit I have long considered switching to something else but the options are endless &amp; all have shortcomings). Unfortunately, it doesn&rsquo;t have a Linux port. As such, WINE to the rescue. But considering I have a bunch of Windows games already on this machine, maybe I could use one of those tools to get Scrivener running.</p>
<p>And oh my, did &lsquo;Lutris&rsquo; deliver. For my experience, it was like 5 steps:</p>
<ol>
<li>Download the latest Scrivener EXE</li>
<li>Install it using &lsquo;Lutris&rsquo; (the <code>+</code> in the top-left of the window)</li>
<li>Configure it to point to the executable: <code>lutrisScrivenerDir/drive_c/Program Files/Scrivener3/Scrivener.exe</code></li>
<li>Delete the <code>textToSpeech</code> directory in <code>lutrisScrivenerDir/drive_c/Program Files/Scrivener3</code></li>
<li>Run Scrivener</li>
</ol>
<p>The weird step here is deleting the <code>textToSpeech</code> directory but that tip came from <a href="https://forum.literatureandlatte.com/t/installing-scrivener-3-1-1-on-linux-wine-7-0-without-problems/127102/25">this forum post</a>.</p>
<p>The next steps are going to be harder, or so I thought. I store my Scrivener files on my Dropbox. I already use <a href="https://maestral.app/">Maestral</a> to have fully-functional Dropbox on my Linux machine and have my <code>.scrivx</code>s stored there. Turns out, the file-picker in WINEd-Scrivener actually exposes <code>root</code> so, all I really had to do was point where I wanted and done.</p>
<p>Now I can actually use Scrivener on all my machines mainly thanks to Lutris doing all the heavy lifting.</p>
<p>(I&rsquo;m aware that this isn&rsquo;t really a &lsquo;dev&rsquo; thing but I thought maybe it could help some others)</p>
]]></content:encoded>
    </item>
    <item>
      <title>butchering a BearBlog word counter for my own needs</title>
      <link>https://lockeb.dev/posts/butchering-a-bearblog-word-counter-for-my-own-needs/</link>
      <pubDate>Wed, 08 Jan 2025 01:03:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/butchering-a-bearblog-word-counter-for-my-own-needs/</guid>
      <description>&lt;p&gt;So I&amp;rsquo;m not a good webdev or JS dev at ALL. Like, I can add and fix things but a large project I would have to spend a lot of time learning things. With that in mind, and after I &lt;em&gt;finally&lt;/em&gt; switched to a paid BearBlog sub, I did some thinking about what I &lt;em&gt;needed&lt;/em&gt; from the BearBlog editor. And basically all I need is a word counter. Simples.&lt;/p&gt;&#xA;&lt;p&gt;Having 0 idea where to start, I did some digging and found almost exactly what I wanted: a &amp;rsquo;time to read&amp;rsquo; snippet from &lt;a href=&#34;https://github.com/Froodooo/bear-plugins/blob/main/bear/reading-time.js&#34;&gt;https://github.com/Froodooo/bear-plugins/blob/main/bear/reading-time.js&lt;/a&gt;. Ideally, this is intended to live on each post and give the reader some info of how long it&amp;rsquo;d take to read a post. But in the guts of this there is what I need: a way to get the word count, and a way to display it on the page.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>So I&rsquo;m not a good webdev or JS dev at ALL. Like, I can add and fix things but a large project I would have to spend a lot of time learning things. With that in mind, and after I <em>finally</em> switched to a paid BearBlog sub, I did some thinking about what I <em>needed</em> from the BearBlog editor. And basically all I need is a word counter. Simples.</p>
<p>Having 0 idea where to start, I did some digging and found almost exactly what I wanted: a &rsquo;time to read&rsquo; snippet from <a href="https://github.com/Froodooo/bear-plugins/blob/main/bear/reading-time.js">https://github.com/Froodooo/bear-plugins/blob/main/bear/reading-time.js</a>. Ideally, this is intended to live on each post and give the reader some info of how long it&rsquo;d take to read a post. But in the guts of this there is what I need: a way to get the word count, and a way to display it on the page.</p>
<p>I made a few changes to the original script and ended up with the following:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span>&lt;<span style="color:#f92672">script</span>&gt; 
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">if</span> (document.<span style="color:#a6e22e">getElementsByName</span>(<span style="color:#e6db74">&#34;body_content&#34;</span>).<span style="color:#a6e22e">length</span> <span style="color:#f92672">&gt;</span> <span style="color:#ae81ff">0</span>) {
</span></span><span style="display:flex;"><span>  <span style="color:#66d9ef">const</span> <span style="color:#a6e22e">wordCount</span> <span style="color:#f92672">=</span> document.<span style="color:#a6e22e">getElementsByName</span>(<span style="color:#e6db74">&#34;body_content&#34;</span>)[<span style="color:#ae81ff">0</span>].<span style="color:#a6e22e">textContent</span>.<span style="color:#a6e22e">trim</span>().<span style="color:#a6e22e">split</span>(<span style="color:#e6db74">/\s+/</span>).<span style="color:#a6e22e">length</span>;
</span></span><span style="display:flex;"><span>  document
</span></span><span style="display:flex;"><span>    .<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#34;main&#34;</span>)
</span></span><span style="display:flex;"><span>    .<span style="color:#a6e22e">insertBefore</span>(
</span></span><span style="display:flex;"><span>      document.<span style="color:#a6e22e">body</span>.<span style="color:#a6e22e">appendChild</span>(
</span></span><span style="display:flex;"><span>        Object.<span style="color:#a6e22e">assign</span>(
</span></span><span style="display:flex;"><span>          document.<span style="color:#a6e22e">createElement</span>(<span style="color:#e6db74">&#34;p&#34;</span>), {
</span></span><span style="display:flex;"><span>          <span style="color:#a6e22e">className</span><span style="color:#f92672">:</span> <span style="color:#e6db74">&#34;word-count&#34;</span>,
</span></span><span style="display:flex;"><span>          <span style="color:#a6e22e">innerHTML</span><span style="color:#f92672">:</span> <span style="color:#e6db74">`Word Count: </span><span style="color:#e6db74">${</span><span style="color:#a6e22e">wordCount</span><span style="color:#e6db74">}</span><span style="color:#e6db74">`</span>
</span></span><span style="display:flex;"><span>        })),
</span></span><span style="display:flex;"><span>      document.<span style="color:#a6e22e">querySelector</span>(<span style="color:#e6db74">&#34;main&#34;</span>).<span style="color:#a6e22e">childNodes</span>[parseInt(document.<span style="color:#a6e22e">currentScript</span>.<span style="color:#a6e22e">getAttribute</span>(<span style="color:#e6db74">&#34;data-before-child&#34;</span>) <span style="color:#f92672">??</span> <span style="color:#ae81ff">4</span>)]);
</span></span><span style="display:flex;"><span>}
</span></span><span style="display:flex;"><span>&lt;/<span style="color:#f92672">script</span>&gt;</span></span></code></pre></div><p>This has some flaws though:</p>
<ul>
<li>It&rsquo;s not particularly accurate. But that&rsquo;s not important</li>
<li>It&rsquo;s static. This is the main drawback with it, is that it requires a page refresh to update. I did play around with <code>KeyboardEvent</code>s for quite a while and got something almost working, but decided that what I have is good enough</li>
<li>I have no idea if it&rsquo;s good JS. Since I made only a few changes to the original, I&rsquo;m relying on the possible fact that <code>Froodooo</code> writes good JS. Well, if I get an angry email from Herman, I&rsquo;ll know something&rsquo;s up.</li>
</ul>
<p>But so far it&rsquo;s been great and quite informative. It&rsquo;s also given me some new ideas of other scripts that I could do (spoiler: check the email button below).</p>
]]></content:encoded>
    </item>
    <item>
      <title>still coasting into hell, 18 months later</title>
      <link>https://lockeb.dev/posts/still-coasting-into-hell-18-months-later/</link>
      <pubDate>Tue, 07 Jan 2025 04:38:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/still-coasting-into-hell-18-months-later/</guid>
      <description>&lt;p&gt;(I am bad at updating this blog but whatever)&lt;/p&gt;&#xA;&lt;p&gt;I took quiet a break from the self-hosting stuff mainly due to reorganising everything and work getting mega busy from late 2023 to late 2024. So what&amp;rsquo;s it look like now?&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;k3s instead of docker, because its so much easier to manage&#xA;&lt;ul&gt;&#xA;&lt;li&gt;tried &lt;code&gt;FluxCD&lt;/code&gt; but managed to break it almost immediately, so switched to &lt;code&gt;ArgoCD&lt;/code&gt; which I know very well&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;Server is now running Proxmox with 2 AlmaLinux nodes. Server is struggling a bit and will probably need to be replaced :(&lt;/li&gt;&#xA;&lt;li&gt;Outside access is still missing mainly due to the new need to tunnel to a remote server and expose via that. Why? Security basically&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;Most of the same goals apply really. Having a Wiki to store long-term useful info. CI for Codeberg. Media hosting and so on and so forth. I don&amp;rsquo;t really want to make the whole list here but instead talk about little bits and pieces, because hoo boy there sure are a lot of little problems everywhere.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>(I am bad at updating this blog but whatever)</p>
<p>I took quiet a break from the self-hosting stuff mainly due to reorganising everything and work getting mega busy from late 2023 to late 2024. So what&rsquo;s it look like now?</p>
<ul>
<li>k3s instead of docker, because its so much easier to manage
<ul>
<li>tried <code>FluxCD</code> but managed to break it almost immediately, so switched to <code>ArgoCD</code> which I know very well</li>
</ul>
</li>
<li>Server is now running Proxmox with 2 AlmaLinux nodes. Server is struggling a bit and will probably need to be replaced :(</li>
<li>Outside access is still missing mainly due to the new need to tunnel to a remote server and expose via that. Why? Security basically</li>
</ul>
<p>Most of the same goals apply really. Having a Wiki to store long-term useful info. CI for Codeberg. Media hosting and so on and so forth. I don&rsquo;t really want to make the whole list here but instead talk about little bits and pieces, because hoo boy there sure are a lot of little problems everywhere.</p>
<p>Let&rsquo;s start with the latest one: filesystem consistency. One goal I have is that I can sync my Bandcamp library and allow uploading of music to a central place, which is then accessible either via browser or SubSonic API. Additionally, it requires the ability to be backed up and accessible as &lsquo;regular&rsquo; files. The way this was done:</p>
<ul>
<li>Create a <code>local-path</code> <code>PersistentVolume</code> to a specific path (e.g. <code>/mnt/storage/music</code>) on a specific node</li>
<li>Force a <code>PVC</code> to use this <code>PV</code> (extremely easy surprisingly)</li>
<li>Have a <code>CronJob</code> run the &lsquo;Bandcamp Sync&rsquo; tool periodically and save into that <code>PV</code></li>
<li>Music server uses that <code>PV</code> as it&rsquo;s storage</li>
<li>Backup script on VM host copies the dir to backup storage</li>
</ul>
<p>This actually worked for a little while, say 2 or 3 days. Until one day I tried to <code>ls</code> the dir and was met with <code>reading directory '.': Bad message</code>. Initially terrifying but straight forward to fix thankfully. Except the fix <code>lost+found</code>&lsquo;ed the entire &lsquo;music&rsquo; dir, which is fine but I don&rsquo;t want to have to run <code>fsck</code> every few days. For now I have scrapped the music stuff and now I need to find the culprit since there seems to be nothing online about this type of issue.</p>
<p>But what are the potential culprits? Let&rsquo;s go from bottom up:</p>
<ul>
<li>The disk/server is shot (unlikely)</li>
<li>The disk being written to by both Proxmox and a VM caused issues</li>
<li>Treating part of the disk as both a Kubernetes <code>PersistentVolume</code> and a regular volume led to various inconsistencies</li>
<li>K3S&rsquo;s <code>local-path</code> <code>StorageClass</code> has issues with the VM disk setup</li>
</ul>
<p>I am not great at fixing Linux filesystem issues so I don&rsquo;t really know but to me any inconsistency in data is brought about by either bad concurrent writes or misunderstanding of the destination. There&rsquo;s a lot of slow testing here but thankfully it&rsquo;s quite easy to do: just run the &lsquo;Bandcamp Sync&rsquo; for a few hours then <code>ls</code> the target dir.</p>
<p>There&rsquo;s a pair of &rsquo;easy&rsquo; solutions in my mind but they make either backing up harder or create too much overhead for my tiny 9 y/o server. Thankfully, part of me wanted to heavily document this homelab set up this time, so once I fix this I can write up the solution (iff I remember).</p>
<p>Unfortunately, I still have 3 or 4 more other problems beyond this that also need to be tackled (including one <em>really</em> annoying physical one) but this I think is the most important as it&rsquo;s one of the key features I want in my homelab.</p>
]]></content:encoded>
    </item>
    <item>
      <title>self-host? more like self-coast-into-hell</title>
      <link>https://lockeb.dev/posts/self-host-more-like-self-coast-into-hell/</link>
      <pubDate>Fri, 07 Jul 2023 21:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/self-host-more-like-self-coast-into-hell/</guid>
      <description>&lt;p&gt;took me a while but i&amp;rsquo;ve been bitten by the self hosting bug. current plans are to run:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;some wiki (wikijs, dokuwiki or &lt;a href=&#34;https://mycorrhiza.wiki/&#34;&gt;mycorrhiza&lt;/a&gt;)&lt;/li&gt;&#xA;&lt;li&gt;commento for adding a comment section to my personal blog&lt;/li&gt;&#xA;&lt;li&gt;jenkins so i can run ci from my codeberg (more about that later) [but also maybe woodpecker instead]&lt;/li&gt;&#xA;&lt;li&gt;some tools to help my partner out with video stuff&lt;/li&gt;&#xA;&lt;li&gt;either wallabag or shaarli for bookmark management (i&amp;rsquo;m a little annoyed with raindop.io)&lt;/li&gt;&#xA;&lt;li&gt;and probably something to replace this gh pages stuff&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;the yunohost image seems like it&amp;rsquo;d be easy to get most of this going. although i have seen a comment that suggests it does some silly things with &lt;code&gt;systemd&lt;/code&gt;&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>took me a while but i&rsquo;ve been bitten by the self hosting bug. current plans are to run:</p>
<ul>
<li>some wiki (wikijs, dokuwiki or <a href="https://mycorrhiza.wiki/">mycorrhiza</a>)</li>
<li>commento for adding a comment section to my personal blog</li>
<li>jenkins so i can run ci from my codeberg (more about that later) [but also maybe woodpecker instead]</li>
<li>some tools to help my partner out with video stuff</li>
<li>either wallabag or shaarli for bookmark management (i&rsquo;m a little annoyed with raindop.io)</li>
<li>and probably something to replace this gh pages stuff</li>
</ul>
<p>the yunohost image seems like it&rsquo;d be easy to get most of this going. although i have seen a comment that suggests it does some silly things with <code>systemd</code></p>
<p>some form of vanilla linux with docker or even k3s/microk8s would also be fine</p>
<h2 id="but-why">but why?</h2>
<p>i deal with too many services and a lot of the nice replacements tend to be require self-hosting. i also want to reduce my dependence on <code>obsidian</code> and also be able to access it at work.</p>
<p>i could also add some fedi* stuff but we&rsquo;ll see. that stuffs expensive on the ol&rsquo; bandwidth</p>
<h2 id="the-missing-thing">the missing thing?</h2>
<p>backups. if i do any of this, i need solid ways to back everything up. i will make a post about that (assuming i ever even get around to all this)</p>
<h2 id="very-quick-sketch">very quick sketch</h2>
<p>i thought it best to also sketch it out. there&rsquo;s a lot missing (volumes, server services) and kinda wrong (the &lsquo;vpn&rsquo; section points the wrong ways), but this is the bulk of my idea. i guess i finally have a project with a defined goal? nice</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/lockeb-dev/drawio.webp" alt="lockelhost"></p>
<p>randomly thought of a good name for this: <code>lockelhost</code></p>
<p>but an even better idea for the domain name</p>
]]></content:encoded>
    </item>
    <item>
      <title>oh boy, another idea</title>
      <link>https://lockeb.dev/posts/oh-boy-another-idea/</link>
      <pubDate>Tue, 20 Jun 2023 21:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/oh-boy-another-idea/</guid>
      <description>&lt;p&gt;I have a new idea for a game. Will it get finished? probably not. but it uses a story I started a few years ago. and it&amp;rsquo;s an excuse to try out &amp;ldquo;Narrat&amp;rdquo; instead of &amp;ldquo;yet another IF in Twine&amp;rdquo;.&lt;/p&gt;&#xA;&lt;hr&gt;&#xA;&lt;p&gt;Until next time, where I&amp;rsquo;ll have this posting setup either fixed (i.e. not written in a Github window) or entirely replaced (goodbye self-hosted?)&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I have a new idea for a game. Will it get finished? probably not. but it uses a story I started a few years ago. and it&rsquo;s an excuse to try out &ldquo;Narrat&rdquo; instead of &ldquo;yet another IF in Twine&rdquo;.</p>
<hr>
<p>Until next time, where I&rsquo;ll have this posting setup either fixed (i.e. not written in a Github window) or entirely replaced (goodbye self-hosted?)</p>
]]></content:encoded>
    </item>
    <item>
      <title>a diversion, one of many</title>
      <link>https://lockeb.dev/posts/a-diversion-one-of-many/</link>
      <pubDate>Sat, 14 Jan 2023 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/a-diversion-one-of-many/</guid>
      <description>&lt;p&gt;Well, this is kind of a shit with respect to my recent posts.&lt;/p&gt;&#xA;&lt;p&gt;0 update on the game. Since work came back this year, it&amp;rsquo;s been a bit tricky to work on it. I&amp;rsquo;ve been focusing on getting my routines and schedules and relaxing back on track. That&amp;rsquo;s not to say I haven&amp;rsquo;t done any outside-of-work coding.&lt;/p&gt;&#xA;&lt;h3 id=&#34;my-problem&#34;&gt;My problem:&lt;/h3&gt;&#xA;&lt;p&gt;I exercise on a stationary bike. I like to track my heartrate, and my pace. Pace on a stationary bike is a bit weird but it&amp;rsquo;s a metric I use to see if body is getting more used to it (I go for long periods without exercising). And I like to track that on Strava so when I do actual rides, I can better compare.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Well, this is kind of a shit with respect to my recent posts.</p>
<p>0 update on the game. Since work came back this year, it&rsquo;s been a bit tricky to work on it. I&rsquo;ve been focusing on getting my routines and schedules and relaxing back on track. That&rsquo;s not to say I haven&rsquo;t done any outside-of-work coding.</p>
<h3 id="my-problem">My problem:</h3>
<p>I exercise on a stationary bike. I like to track my heartrate, and my pace. Pace on a stationary bike is a bit weird but it&rsquo;s a metric I use to see if body is getting more used to it (I go for long periods without exercising). And I like to track that on Strava so when I do actual rides, I can better compare.</p>
<h3 id="solution">Solution:</h3>
<p>Smart-watch. Tracks heart rate and exercise specifics. Pace is missing but the good, important stuff is there. But I really want to record my distance to calculate my pace.</p>
<p>Can I enter my distance in somewhere? For Polar, yes you can. Great! Oh, an allergic reaction means you have to try a dozen different watch bands. Thanks to an underwhelming 3rd party market, there aren&rsquo;t any straps that are big enough for my watch.</p>
<p>Hrmm, which smartwatch does have that? Fitbit! Cool, back to Fitbit <code>&lt;/s&gt;</code>. Oh it now has &ldquo;Spinning&rdquo; as a workout option.</p>
<p>Can I enter my distance? No. Hrmm, what if I used the &ldquo;Ride&rdquo; workout? No.</p>
<p>So how can I get this into Strava? Oh, I can have Fitbit automatically upload exercise data to Strava.</p>
<p>Oh why isn&rsquo;t it working? &ldquo;Spinning&rdquo; doesn&rsquo;t record a heart-rate so Strava won&rsquo;t recognise it, and &ldquo;Ride&rdquo;, since I&rsquo;m stationary, doesn&rsquo;t record a distance.</p>
<h3 id="the-actual-problem">The (actual) problem:</h3>
<p>When I was using Polar, my process would involve: sync watch, load Polar dashboard on browser, open recorded exercise, for lap 1 alter the distance to match what I did, export exercise as a TCX file, upload to Strava.</p>
<p>But Fitbit, I can&rsquo;t do this, but I can export an exercise as a TCX file. So, that&rsquo;s what I did and I was horrified. If your activity is set to &ldquo;Spinning&rdquo;, the TCX file only records the start time and the end time. However, if it&rsquo;s set to &ldquo;Ride&rdquo;, it exports a segment every 5 seconds with the current heart rate, but a distance of 0. Oh easy right, lets just use &ldquo;Ride&rdquo; and manually add the distance to the TCX file.</p>
<p>Not so. Strava calculates distance based on the total distance accumulated from each segment. So if I rode for 30 minutes, I would need to alter 360 segments and do something like distance/(time*60/5) for each segment. That&rsquo;s too annoying, especially by hand. But there is a field called <code>DistanceMeters</code> I can use. Oh nope. Since &ldquo;Ride&rdquo; also records lat/lon, Strava will think there&rsquo;s distance in that segment if it sees the lat/lon. Easy, remove all the lat/lon and segment distances.</p>
<p>And that&rsquo;s the solution: Use the &ldquo;Ride&rdquo; workout, scrub all the lat/lon and distances from the segments, and add the total distance to the parent <code>DistanceMeters</code>. Of course, this isn&rsquo;t that easy to do. But still, <code>tcxa</code> (TCX Anonymiser) exists and does just that.</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>tcxa.exe -i input-file.tcx -o output-file.tcx -d distanceInMetres</span></span></code></pre></div><p>It&rsquo;s in <code>Rust</code>, it&rsquo;s ugly as hell, but it does exactly what I want.</p>
<h3 id="next-step">Next step:</h3>
<p>This is too ugly. My next version of this will instead call the Fitbit API, get the HR and exercise data, ask for the distance, and output a TCX to upload to Strava (ideally all in a browser). Next step from there is remove the manual upload, but that&rsquo;s going to be a long time. This way I can stop using &ldquo;Ride&rdquo; and instead use &ldquo;Spinning&rdquo;, which means I won&rsquo;t upload any positional data to Fitbit.</p>
<p>We&rsquo;ll see when that happens&hellip;</p>
<h2 id="the-game">The game:</h2>
<p>I&rsquo;ll get back to it soon. I&rsquo;ve been enjoying playing games a bit too much as well, but that has been good I think.</p>
<hr>
<p>Until next time, where my head will be mashed by trying to do something wacky with K8S.</p>
]]></content:encoded>
    </item>
    <item>
      <title>new year new m</title>
      <link>https://lockeb.dev/posts/new-year-new-m/</link>
      <pubDate>Sat, 31 Dec 2022 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/new-year-new-m/</guid>
      <description>&lt;p&gt;Well in continuing with the fortnightly updates, the fifth(!) in this series lands on new years day. And I am tired. Luckily (or not), there&amp;rsquo;s not too much to talk about. I have taken a few days off this fortnight from it to work on some other things and also relax. I did start playing Final Fantasy Tactics for the first time in many, many years, and that has given me a whole bunch of new ideas.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Well in continuing with the fortnightly updates, the fifth(!) in this series lands on new years day. And I am tired. Luckily (or not), there&rsquo;s not too much to talk about. I have taken a few days off this fortnight from it to work on some other things and also relax. I did start playing Final Fantasy Tactics for the first time in many, many years, and that has given me a whole bunch of new ideas.</p>
<p>Since last time, we now have:</p>
<ul>
<li>Cutscenes</li>
<li>Rotation</li>
<li>&gt; 1 height tiles!</li>
<li>Level importing/exporting</li>
<li>A level editor!</li>
</ul>
<p>In addition to these things, I&rsquo;ve also spent a bunch of time in spreadsheets figuring out rules and stats. We&rsquo;re actually getting somewhere which is nice.
I won&rsquo;t write much about the tile height stuff. Just that it was a pain because they kept drawing in insane locations. However, I&rsquo;m still not 100% set on the method I ended up with. It&rsquo;s likely in the future I&rsquo;ll investigate the cooler method I was trying which allowed any height and width structures made of tiles. Does height actually matter though in gameplay yet? Nope.</p>
<h3 id="rotation">Rotation</h3>
<p>This was a biggy, and also kinda simple once I realised I was reading from the wrong matrix&hellip; There are 4 rotations now and it is really cool being able to see the battlefield from these angles. There are <em>some</em> issues though e.g. some tiles lose their meaning in other orientations. I&rsquo;ll figure that out later and decide if it&rsquo;s really worth keeping.</p>
<h3 id="cutscenes">Cutscenes</h3>
<p>They are in a traditional visual novel style. They have their own JSONs as well and I can do an awful lot with them already. I won&rsquo;t post a picture because it is very ugly with placeholders and flat fills. Maybe soon. The cutscene player has a typewriter mode and automatic text-wrapping so I don&rsquo;t need to add <code>\n</code> in the dialogue manually (unless I want to). This was pretty easy to do, although I spent lot of time having the text being cut off really early. Spent a good 30 minutes investigating that to only find the wrap value was set to the height of the textbox and not the width. Ooops. I do need to spend some more time with fonts because I just can&rsquo;t find one I like.</p>
<h3 id="level-editor--importingexporting">Level editor &amp; importing/exporting</h3>
<p><img src="https://i.imgur.com/xBSLFES.png" alt=""></p>
<p>This was borne out of necessity. It actually begun with level generation. I started writing a random level generator because a) infinite levels, and b) I&rsquo;m not a level designer. After a day<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> or so of work, I began to realise that maybe generation would get me 75% of the way and the rest would need to be tweaked manually. So I wrote an exporter for the levels. It took about 20 minutes and most of that time was spent deliberating how they should be stored. I chose a way that was ~27% more space efficient than the simplest way and still maintains some readability. Considering my maps are currently 20x20 i.e. 400 tiles, it&rsquo;s still not so readable.
Entries kinda look like:</p>





<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-json" data-lang="json"><span style="display:flex;"><span>{
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">&#34;tile_sprite_id&#34;</span>: { <span style="color:#f92672">&#34;coords&#34;</span>: [<span style="color:#e6db74">&#34;x1,y1&#34;</span>, <span style="color:#e6db74">&#34;x2,y2&#34;</span>] }
</span></span><span style="display:flex;"><span>}</span></span></code></pre></div><p>At this point I was <em>seriously</em> thinking of editing the points in the JSON. Yes, that was insane. And that&rsquo;s how the level editor came to be. Again, it was very simple, about an hour of work and I could load in the level JSON, click on each tile to cycle through the available tile sprites and then export (albeit to <code>stdout</code> but still). I guess I&rsquo;m going to have to learn some level design, or just play more tactics games. I still have a few things I need to consider &amp; implement such as depth, cover and line-of-sight.</p>
<hr>
<p>I&rsquo;m back at work as of tomorrow and back to my old routines, so there&rsquo;ll be a couple of hours work on this a week which kinda sucks, especially since some hard bits are coming up and I can&rsquo;t just do them in front of the TV. Also actually thinking about narrative again and since this will be part of the universe I set my book in, I need to check my notes.</p>
<p>Until next time (probably in another 2 weeks. Maybe)</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>A day is a bit subjective and changeable. 30 minutes minimum to 4 hours max&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>400 diamonds</title>
      <link>https://lockeb.dev/posts/400-diamonds/</link>
      <pubDate>Sat, 17 Dec 2022 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/400-diamonds/</guid>
      <description>&lt;p&gt;And after 2 weeks, I&amp;rsquo;m still plodding along. What does it look like now? Well&amp;hellip;&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://bear-images.sfo2.cdn.digitaloceanspaces.com/lockeb-dev/20221218.gif&#34; alt=&#34;20221218&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;We have:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Units!&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Animation&lt;/li&gt;&#xA;&lt;li&gt;Movement&lt;/li&gt;&#xA;&lt;li&gt;Turns&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;A map..&lt;/li&gt;&#xA;&lt;li&gt;Parallax backgrounds&lt;/li&gt;&#xA;&lt;li&gt;A bunch of UI gunk&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Buttons!&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;At least, that&amp;rsquo;s what you can see. I&amp;rsquo;ve spent quite an amount of time working on backend-y things to help once I get the gameplay sorted (or tbh started). Basically, lots of JSON files. For example, here is the main battle scene:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>And after 2 weeks, I&rsquo;m still plodding along. What does it look like now? Well&hellip;</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/lockeb-dev/20221218.gif" alt="20221218"></p>
<p>We have:</p>
<ul>
<li>Units!
<ul>
<li>Animation</li>
<li>Movement</li>
<li>Turns</li>
</ul>
</li>
<li>A map..</li>
<li>Parallax backgrounds</li>
<li>A bunch of UI gunk
<ul>
<li>Buttons!</li>
</ul>
</li>
</ul>
<p>At least, that&rsquo;s what you can see. I&rsquo;ve spent quite an amount of time working on backend-y things to help once I get the gameplay sorted (or tbh started). Basically, lots of JSON files. For example, here is the main battle scene:</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/lockeb-dev/screenshot2022-12-18095358.webp" alt="Screenshot2022-12-18095358"></p>
<p>This took some degree of thinking (by which I mean I couldn&rsquo;t do this with the TV on) and there are JSONs to describe pretty much every aspect of the game and its assets. This actually paid off when I wanted to try a new UI layout with more boxes and text (as is shown in the GIF). But of course I could add hundreds of options to the JSON but I think once the dialogue scenes are done, I&rsquo;ll have the JSONs&rsquo; schemas mostly done.</p>
<p>However, since the last post, two things caused more hassle than anything else: the parallax background and the text.</p>
<h2 id="the-parallax-backgrounds">The parallax backgrounds</h2>
<p>Since I long decided (by accident) to consider every draw to be explicitly layer images up images (which very closely matches Ebitengine&rsquo;s paradigm but I make it <em>worse</em>), I don&rsquo;t actually have a system that resembles a camera. It&rsquo;s all just sequential draws that compose an image that is then drawn to the screen. This will soon bite me with the last feature I want to add but I&rsquo;ll deal with that over Xmas. So, what is the problem here? Well, parallax images are animations layered with each layer playing or moving at different speeds to give the illusion of depth. How do I do it here? I take the background images, tile them so they take up the screen width or height + 1 of the raw tile width/height as a buffer and then tween their draw positions along at different rates. It&rsquo;s not a good way of doing it but it works really well!</p>
<h2 id="the-text">The text</h2>
<p>Ebitengine&rsquo;s text module is actually pretty good and would have been fine for this project. Unfortunately it always looked kind of jank when drawn, even in nearest-neighbour style draw modes. I assumed this to be an issue with the module itself so I started using <code>etxt</code> which is a wonderful library that aims to fix all the typeface and font problems in Ebitengine&rsquo;s own text module. This garnered me the same result. Perplexed, I did some reading and it turns out this was actually a limitation in the <code>golang</code> <code>image</code> module itself (I have forgotten exactly what though). Solution: bitmap fonts. Ebitengine has a module for that but only with 2 or 3 typefaces. So I built my own. It takes some of the ideas of <code>etxt</code> and jams bitmaps into it. Long way to go before I&rsquo;m happy with it <em>in this project</em> but if I was to find anything to rip out and make available it would be this.</p>
<hr>
<p>So what happens now? A lot of things. Gameplay first, then the cutscenes. I know I&rsquo;m not doing anything ground breaking but I haven&rsquo;t been this interested in making a game for 9 years and as much as I think <code>golang</code> is a language best <em>not</em> used (I had hoped to do this in Rust), I gelled really well with <code>ebitengine</code>. Maybe my other idea will be in Rust (w/ Bevy).
Oh and shaders, I have to properly learn about them now.</p>
<p>Until next time (probably in another 2 weeks)</p>
]]></content:encoded>
    </item>
    <item>
      <title>golang? I hardly know him-g</title>
      <link>https://lockeb.dev/posts/golang-i-hardly-know-him-g/</link>
      <pubDate>Sat, 03 Dec 2022 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/golang-i-hardly-know-him-g/</guid>
      <description>&lt;p&gt;So there&amp;rsquo;s been some more from the previous post. I quite like &lt;code&gt;golang&lt;/code&gt; I think, although the lack of actual concrete style rules is very weird as a Google product but hey, I can live with that.&lt;/p&gt;&#xA;&lt;p&gt;BUT! In my maybe an hour a day of wrangling with &lt;code&gt;golang&lt;/code&gt; and &lt;code&gt;ebitengine&lt;/code&gt; I&amp;rsquo;ve actually gotten somewhere. There has also been a LOT of refactoring to get things to behave nicer and faster&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. Maybe once this goes a bit further I&amp;rsquo;ll do a quick architecture overview but it&amp;rsquo;s going to look a lot like normal ECS &amp;amp; &amp;ldquo;scene-based&amp;rdquo; game-dev architectures because, well, that&amp;rsquo;s basically what I&amp;rsquo;ve been doing&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. There&amp;rsquo;s one thing my brain sucks at and that&amp;rsquo;s geometry. Since I can&amp;rsquo;t visualise stuff (&lt;a href=&#34;https://en.wikipedia.org/wiki/Aphantasia&#34;&gt;Aphantasia&lt;/a&gt; and all) doing geometric calculations sucks. So I spent a lot of my time refactoring in such a way I would be able to do fewer of them. And I got it down to 2 from 5. Pretty good. But what was that main hurdle:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>So there&rsquo;s been some more from the previous post. I quite like <code>golang</code> I think, although the lack of actual concrete style rules is very weird as a Google product but hey, I can live with that.</p>
<p>BUT! In my maybe an hour a day of wrangling with <code>golang</code> and <code>ebitengine</code> I&rsquo;ve actually gotten somewhere. There has also been a LOT of refactoring to get things to behave nicer and faster<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>. Maybe once this goes a bit further I&rsquo;ll do a quick architecture overview but it&rsquo;s going to look a lot like normal ECS &amp; &ldquo;scene-based&rdquo; game-dev architectures because, well, that&rsquo;s basically what I&rsquo;ve been doing<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. There&rsquo;s one thing my brain sucks at and that&rsquo;s geometry. Since I can&rsquo;t visualise stuff (<a href="https://en.wikipedia.org/wiki/Aphantasia">Aphantasia</a> and all) doing geometric calculations sucks. So I spent a lot of my time refactoring in such a way I would be able to do fewer of them. And I got it down to 2 from 5. Pretty good. But what was that main hurdle:</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/lockeb-dev/setfirstgroundselect.gif" alt="setfirstgroundselect"></p>
<p>Yep, looks pretty <em>okay</em> I would say. Highlighting tiles is pretty important in what I have planned (TB/S RPG probably but maybe more). But as you can see, there is still minor hiccough. There&rsquo;s a LOT still to come (my to-do list<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup> is ever expanding) but this is a big, big hurdle to get over.</p>
<p>Of course I did make it hard for myself by trying to have the tiles generate their highlighted state automatically but it was very ineffective, but I&rsquo;m keeping that code for later since it might work in other contexts.</p>
<p>I also have an idea of how this game should sound but we are a looooong way from that.</p>
<p>I guess next week there may be something more, unless I get bored or frustrated.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>who knew that initialising an <code>ebiten.Image</code> 60 times a second might eventually cause issues&hellip;&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>but as I usually do, off the top of my head without reading anything :+1:&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>I might write up something about task tracking in different projects because different methods tickle my brain in different ways&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Well, well, well</title>
      <link>https://lockeb.dev/posts/well-well-well/</link>
      <pubDate>Sat, 26 Nov 2022 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/well-well-well/</guid>
      <description>&lt;p&gt;I&amp;rsquo;m getting back into gamedev slowly&lt;/p&gt;&#xA;&lt;p&gt;I wanted to do something in &lt;code&gt;Rust&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;Then &lt;code&gt;Godot 4&lt;/code&gt; (whenever that is stable)&lt;/p&gt;&#xA;&lt;p&gt;But now due to&amp;hellip;external ideas, &lt;code&gt;go&lt;/code&gt;&lt;/p&gt;&#xA;&lt;p&gt;More specifically &lt;code&gt;ebitengine&lt;/code&gt; (terrible name, nice engine with a wacky concept)&lt;/p&gt;&#xA;&lt;p&gt;&lt;img src=&#34;https://bear-images.sfo2.cdn.digitaloceanspaces.com/lockeb-dev/helloworldebitenegineandsomedafetileset.webp&#34; alt=&#34;A screen shot of a window showing a few pixel art tiles of ground and the words &amp;ldquo;Hello World&amp;rdquo;&#34;&gt;&lt;/p&gt;&#xA;&lt;p&gt;We&amp;rsquo;ll see where this goes, if anywhere&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I&rsquo;m getting back into gamedev slowly</p>
<p>I wanted to do something in <code>Rust</code></p>
<p>Then <code>Godot 4</code> (whenever that is stable)</p>
<p>But now due to&hellip;external ideas, <code>go</code></p>
<p>More specifically <code>ebitengine</code> (terrible name, nice engine with a wacky concept)</p>
<p><img src="https://bear-images.sfo2.cdn.digitaloceanspaces.com/lockeb-dev/helloworldebitenegineandsomedafetileset.webp" alt="A screen shot of a window showing a few pixel art tiles of ground and the words &ldquo;Hello World&rdquo;"></p>
<p>We&rsquo;ll see where this goes, if anywhere</p>
]]></content:encoded>
    </item>
    <item>
      <title>Well shucks I appeared</title>
      <link>https://lockeb.dev/posts/well-shucks-i-appeared/</link>
      <pubDate>Sat, 29 Oct 2022 21:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/well-shucks-i-appeared/</guid>
      <description>&lt;h2 id=&#34;waooh&#34;&gt;Waooh&lt;/h2&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t appear very often, especially here BUT since the last post:&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Got job at Elisa Polystar&lt;/li&gt;&#xA;&lt;li&gt;I tried to make a VIC-20 emulator. It kinda worked until trying to get keyboard stuff to behave but you it runs VIC-20 stuff which is nice. Also it was written in Kotlin because work got me on that bandwagon.&lt;/li&gt;&#xA;&lt;li&gt;Promoted to senior developer&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;That&amp;rsquo;s about it considering the purpose of this blog.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="waooh">Waooh</h2>
<p>I don&rsquo;t appear very often, especially here BUT since the last post:</p>
<ul>
<li>Got job at Elisa Polystar</li>
<li>I tried to make a VIC-20 emulator. It kinda worked until trying to get keyboard stuff to behave but you it runs VIC-20 stuff which is nice. Also it was written in Kotlin because work got me on that bandwagon.</li>
<li>Promoted to senior developer</li>
</ul>
<p>That&rsquo;s about it considering the purpose of this blog.</p>
<p>SO SO SO SO SO SO</p>
<p>What am I doing outside of work for dev things?
Well, I&rsquo;m trying to think of a project that uses:</p>
<ul>
<li>Rust</li>
<li>Wasm</li>
<li>Typescript</li>
<li>RabbitMQ</li>
<li>AWS</li>
</ul>
<p>Apart from that, I have nooooooo idea what to do. Maybe I&rsquo;ll write and discuss ideas here.</p>
<p>Assuming I remember that here is here.</p>
<p>Until then..</p>
]]></content:encoded>
    </item>
    <item>
      <title>Yate I guess?</title>
      <link>https://lockeb.dev/posts/yate-i-guess/</link>
      <pubDate>Sat, 15 Feb 2020 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/yate-i-guess/</guid>
      <description>&lt;h2 id=&#34;making-some-tools-to-make-someones-life-easier&#34;&gt;Making some tools to make someone’s? life easier&lt;/h2&gt;&#xA;&lt;p&gt;Deploying Twine stories as executables is slightly annoying, especially when working across multiple platforms. In the &amp;ldquo;Reclaiming Fibres&amp;rdquo; post, I devised a structure for simplifying this while keeping it logical for VCSs. However, lots of Twine users don&amp;rsquo;t use any VCS and it&amp;rsquo;d be easier to use a standalone application to package things for release.&lt;/p&gt;&#xA;&lt;p&gt;So I see 2 main problems here:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="making-some-tools-to-make-someones-life-easier">Making some tools to make someone’s? life easier</h2>
<p>Deploying Twine stories as executables is slightly annoying, especially when working across multiple platforms. In the &ldquo;Reclaiming Fibres&rdquo; post, I devised a structure for simplifying this while keeping it logical for VCSs. However, lots of Twine users don&rsquo;t use any VCS and it&rsquo;d be easier to use a standalone application to package things for release.</p>
<p>So I see 2 main problems here:</p>
<ol>
<li>How can we make this easy while still being platform and user independent?</li>
<li>Interoperability with the Twine2 structure</li>
</ol>
<p>Problem 1 is where the bulk of this post lies.</p>
<p>I still plan on using electron to package the executables. This requires NPM/NPX to do. As such, writing this in something that depends on NPM/NPX is slightly problematic for the non-technical user. This pushed me to make it in something else, however, the ease of use consideration made this choice easy. I decided on Python as prior experience with GUI development in C++ and Java is painful. A package for Python called &ldquo;PySimpleGUI&rdquo; makes this VERY easy. The problem now becomes a design problem.</p>
<p>So, this tool (or set of tools really) has to accomplish certain tasks:</p>
<ul>
<li>Set up the Electron app builder directory</li>
<li>Move all the necessary Twine, HTML, and other files to the correct directory</li>
<li>Add the correct data to the various JSON files</li>
<li>Build the app for Platform X</li>
<li>Build the app for Web</li>
</ul>
<p>In it&rsquo;s current state, it treats each new build as an entirely new Electron app. Which means lots of NPM downloads, and it doesn&rsquo;t alter the Electron config files. My goal is to have this as a single program, with two main functions: 1) setup the Electron app builder directory, 2) build an executable.</p>
<p>Cool. Great. But back up to problem 2. How do we cater for people that only user Twine2?
Of course, this shadows another problem but alas.
I think the <em>best</em> port of call for this is to rely on the Twine2 user to &ldquo;Publish to HTML&rdquo;.</p>
<p>The proposed workflow for a Twine 2 user is as follows:</p>
<ol>
<li>Work on story</li>
<li>Publish to HTML to any directory</li>
<li>Open my app, select the HTML file, choose a directory to build in</li>
<li>Build directory, copy HTML to it</li>
<li>Alter settings (if needed)</li>
<li>Build executable</li>
</ol>
<p>In the case the entire story is self-contained as an HTML file, done! But of course, thats not always the case. I fear it may even be very seldom the case.</p>
<p>What happens if you have images and audio included? We now run into a problem that Twine2 handles differently compared to using Tweego and CLI. Paths are absolute compared to relative. In the latter, this is easy (assuming the author is logical) because a common structure is usually followed:</p>





<pre tabindex="0"><code>twine_project_dir/
    story.html
    imgs/
        an_image.png
    audio/
        some_audio.mp3</code></pre><p>Easy. Copy <code>twine_project_dir</code> to the Electron directory.
Twine2 is not so simple. Potential solutions are:</p>
<ul>
<li>Parse the story file, copy all the images and audio to local directories, replace the paths</li>
<li>Make the author conform to the above structure manually</li>
<li>Prompt the user to move their audio and images to the Electron directory and update their story</li>
</ul>
<p>None of these options are nice and it will take a while to think this through.</p>
<p>I&rsquo;ll make a post once I&rsquo;ve finished this app (currently known as YATE) to see which design decisions I ended up making.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Unity, (synthetic) Audio, and YOU!</title>
      <link>https://lockeb.dev/posts/unity-synthetic-audio-and-you/</link>
      <pubDate>Wed, 05 Feb 2020 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/unity-synthetic-audio-and-you/</guid>
      <description>&lt;h2 id=&#34;well-me&#34;&gt;(Well, me)&lt;/h2&gt;&#xA;&lt;p&gt;I&amp;rsquo;ve just spent a week getting acclimatised to Unity (it&amp;rsquo;s been 7 years since I used it last&amp;hellip;) for a project I want finished by the 1st of March.&lt;/p&gt;&#xA;&lt;p&gt;I don&amp;rsquo;t feel like divulging too much since otherwise I&amp;rsquo;ll probably not get on with it, BUT, it involves a lot of audio synthesis and Twine.&lt;/p&gt;&#xA;&lt;p&gt;Audio synthesis in Unity is&amp;hellip;interesting. After a week it makes a LOT more sense, but this is most likely me understanding how Unity -actually- works. Of course, Unity has a HUGE community and audio synthesis tools exist. But as is always the way, the good ones require $$$. Some not-very-thorough digging resulted in some open source synthesis tools&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; and pretty much work as is. &amp;ldquo;Pretty much&amp;rdquo; is where it gets funky.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="well-me">(Well, me)</h2>
<p>I&rsquo;ve just spent a week getting acclimatised to Unity (it&rsquo;s been 7 years since I used it last&hellip;) for a project I want finished by the 1st of March.</p>
<p>I don&rsquo;t feel like divulging too much since otherwise I&rsquo;ll probably not get on with it, BUT, it involves a lot of audio synthesis and Twine.</p>
<p>Audio synthesis in Unity is&hellip;interesting. After a week it makes a LOT more sense, but this is most likely me understanding how Unity -actually- works. Of course, Unity has a HUGE community and audio synthesis tools exist. But as is always the way, the good ones require $$$. Some not-very-thorough digging resulted in some open source synthesis tools<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> and pretty much work as is. &ldquo;Pretty much&rdquo; is where it gets funky.</p>
<p>Enter sequencing. I started this by making a clock. That&hellip;wasn&rsquo;t enough. Random dead open source project to the rescue<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. Now I had audio file sequencing. Useful, but not what I needed. A whole lot of tweaking and testing later I know have a set of sequencers and synthetic instruments. Nothing fantastic, but I&rsquo;m gradually making it more modular and you can guess where this is going.</p>
<p>BUT NOT YET</p>
<p>I want to do this project (or at least get a proof-of-concept out) before going overboard into software modular synthesis<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>. A secondary likely splinter project that will appear is expanding Cradle<sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup> (the Twine &gt; Unity framework) to do some more things.</p>
<p>Alas, where it stands right now requires more work into thinking how other parts work before blowing up my todo list. So instead I&rsquo;ll be (attemping to) jam over the next few days.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://github.com/pixlpa/Unity-Synth-Experiments">https://github.com/pixlpa/Unity-Synth-Experiments</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p><a href="https://github.com/Ludomancer/Unity-Audio-Sequencer">https://github.com/Ludomancer/Unity-Audio-Sequencer</a>&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>I mean FFS we have the glorious VCV rack for that but still, for inside Unity stuff.&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p><a href="https://github.com/daterre/Cradle">https://github.com/daterre/Cradle</a>&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>autoCalendar</title>
      <link>https://lockeb.dev/posts/autocalendar/</link>
      <pubDate>Sun, 02 Feb 2020 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/autocalendar/</guid>
      <description>&lt;p&gt;I&amp;rsquo;ve always wanted an auto resizing calendar based on the year and month I want. Particularly, I&amp;rsquo;ve wanted this in Google Sheets.&lt;/p&gt;&#xA;&lt;p&gt;Why?&lt;/p&gt;&#xA;&lt;p&gt;So I can print it off and have it take up as much of as A4 page as required.&lt;/p&gt;&#xA;&lt;p&gt;Now I&amp;rsquo;ve done it.&lt;/p&gt;&#xA;&lt;p&gt;Here&amp;rsquo;s the gist for it: &lt;a href=&#34;https://gist.github.com/LockeBirdsey/746c0f99b3b75960c8bc9b6d86a0f576&#34;&gt;https://gist.github.com/LockeBirdsey/746c0f99b3b75960c8bc9b6d86a0f576&lt;/a&gt;&lt;/p&gt;&#xA;&lt;p&gt;Now I have an infinite calendar that can be printed. Yay?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I&rsquo;ve always wanted an auto resizing calendar based on the year and month I want. Particularly, I&rsquo;ve wanted this in Google Sheets.</p>
<p>Why?</p>
<p>So I can print it off and have it take up as much of as A4 page as required.</p>
<p>Now I&rsquo;ve done it.</p>
<p>Here&rsquo;s the gist for it: <a href="https://gist.github.com/LockeBirdsey/746c0f99b3b75960c8bc9b6d86a0f576">https://gist.github.com/LockeBirdsey/746c0f99b3b75960c8bc9b6d86a0f576</a></p>
<p>Now I have an infinite calendar that can be printed. Yay?</p>
]]></content:encoded>
    </item>
    <item>
      <title>Icons icns ico</title>
      <link>https://lockeb.dev/posts/icons-icns-ico/</link>
      <pubDate>Sat, 01 Feb 2020 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/icons-icns-ico/</guid>
      <description>&lt;p&gt;There&amp;rsquo;s 2 more gists that should make life much easier for me and potentially others.&lt;br&gt;&#xA;They&amp;rsquo;re all about making icons from a simple PNG. For both macOS(icns) and Windows(ico). The ico gist can also be used to make favicons, which is a nice additional feature.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://gist.github.com/LockeBirdsey/0d5cf2b11462ffa1d48905acdb7e1089&#34;&gt;pngToICNS&lt;/a&gt;&lt;/li&gt;&#xA;&lt;li&gt;&lt;a href=&#34;https://gist.github.com/LockeBirdsey/e4a311b8c3563a8620b977a94042af87&#34;&gt;pngToICO&lt;/a&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I have to get testing these things on Windows (and no, not just WSL) rather soon.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>There&rsquo;s 2 more gists that should make life much easier for me and potentially others.<br>
They&rsquo;re all about making icons from a simple PNG. For both macOS(icns) and Windows(ico). The ico gist can also be used to make favicons, which is a nice additional feature.</p>
<ul>
<li><a href="https://gist.github.com/LockeBirdsey/0d5cf2b11462ffa1d48905acdb7e1089">pngToICNS</a></li>
<li><a href="https://gist.github.com/LockeBirdsey/e4a311b8c3563a8620b977a94042af87">pngToICO</a></li>
</ul>
<p>I have to get testing these things on Windows (and no, not just WSL) rather soon.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Reclaiming Fibres</title>
      <link>https://lockeb.dev/posts/reclaiming-fibres/</link>
      <pubDate>Fri, 31 Jan 2020 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/reclaiming-fibres/</guid>
      <description>&lt;p&gt;Many eons ago, I used to make interactive fiction.&lt;br&gt;&#xA;I was good at it.&lt;/p&gt;&#xA;&lt;p&gt;So I&amp;rsquo;m trying to get them back up and working again. And boyyy is it taking a while. So I might run through the steps. It has been a LONG time since I checked out the Twine scene, and as such, I&amp;rsquo;m rather behind on developments.&lt;/p&gt;&#xA;&lt;h2 id=&#34;from-twine-1-to-twine-2&#34;&gt;From Twine 1 to Twine 2&lt;/h2&gt;&#xA;&lt;p&gt;Fibres was made a long time ago (2012 or 2013). Twine 1 (or more importantly Twee2) was the cutting edge. The story format (Sugarcube) had some limitations, so custom macros were all the rage. Porting from Twine 1 to 2 was easy. A tool that advertised as such could be downloaded and ran. Did it work? Of course not. It was from 2015, what did I expect?&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt; Take 2: Maybe Twine&amp;rsquo;s export to Twee code feature would produce a file that could be imported into Twine 2. Ei/non/no. Twine 2 can only import compatible HTML files. Take 3: Generate the HTML from Twine 1 and import into Twine 2. Ei/non/no. Silent failures on both in browser and downloaded versions of Twine 2 &lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;. What to do?&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Many eons ago, I used to make interactive fiction.<br>
I was good at it.</p>
<p>So I&rsquo;m trying to get them back up and working again. And boyyy is it taking a while. So I might run through the steps. It has been a LONG time since I checked out the Twine scene, and as such, I&rsquo;m rather behind on developments.</p>
<h2 id="from-twine-1-to-twine-2">From Twine 1 to Twine 2</h2>
<p>Fibres was made a long time ago (2012 or 2013). Twine 1 (or more importantly Twee2) was the cutting edge. The story format (Sugarcube) had some limitations, so custom macros were all the rage. Porting from Twine 1 to 2 was easy. A tool that advertised as such could be downloaded and ran. Did it work? Of course not. It was from 2015, what did I expect?<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> Take 2: Maybe Twine&rsquo;s export to Twee code feature would produce a file that could be imported into Twine 2. Ei/non/no. Twine 2 can only import compatible HTML files. Take 3: Generate the HTML from Twine 1 and import into Twine 2. Ei/non/no. Silent failures on both in browser and downloaded versions of Twine 2 <sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>. What to do?</p>
<p>Well, tweego exists<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>. And can do some cool things. Like convert between versions of Twee code, but most importantly export to Twine 1 or 2 archives. C&rsquo;est magnifique!</p>
<p><code>tweego my-poor-twee-file.tw2 -a -o output-to-twine2.html</code></p>
<p>Import into Twine 2 and suddenly it appears.<br>
Oh god, the issues.</p>
<p>So those custom macros I mentioned? Well, the JS for them no longer works. Bollocks I hear you say. Never. Twine macros are Story Format dependent. <code>Fibres</code> used <code>Sugarcube</code>, a Twine 1 format. A increased captial version exists for Twine 2 called <code>SugarCube</code>. As it just so wonderfully turns out, my custom macros are now core in <code>SugarCube</code>. Just with different names and parameters. Regex made short work of that.</p>
<p>An interesting issue that was probably exclusive to me was a passage link failing on a number of chapters. Specifically:</p>
<p><code>[[--&gt;|Passage]]</code></p>
<p>The documentation for linking is quite straight forward: <code>[[Text|Link]]</code>. So why does <code>--&gt;</code> fail?<br>
Well, how are Twine2 files stored? HTML. And what is a comment in HTML? That&rsquo;s right
<code>&lt;!--comment--&gt;</code><br>
Easy fix, just replace &ndash;&gt; with literally anything else.</p>
<p>And Fibres comes to life. Glorious.</p>
<p>Intermission<code>&lt;blink&gt;&lt;marquee&gt;</code></p>
<h3 id="a-caveat-twine-version-control">A Caveat: Twine Version Control</h3>
<p>A big surprise to me is that NONE of my Twine projects were in any form of version control outside of Dropbox. Something that needed to be fixed in the middle of all this. Because of how Twine 2 behaves, this is not a straightforward solve.</p>
<p>The main issues:</p>
<ul>
<li>Twine 2 runs as an Electron app, and doesn&rsquo;t include any features for selecting where stories may live.</li>
<li>Well, having to use Twine 2 since it&rsquo;s a really nice tool and I don&rsquo;t want to edit branching stories in Sublime Text.</li>
</ul>
<p><strong>Stage 1: Get the essentials into a repo.</strong><br>
Twine 1 source file, Twee2 file, and the Tweego converted Twee3 file. Cool. Bananas. A starting point.</p>
<p><strong>Stage 2: Use Twine 2 to edit and update these files</strong>
Twine 2 does use a /nice/ directory for storing stories which makes this easier, namely <code>$HOME/Documents/Twine</code><br>
We need to prepare our Twee file for use in it.</p>
<p><code>tweego Fibres.twee --archive-twine2 --output=$HOME/Documents/Twine/Stories</code><sup id="fnref:4"><a href="#fn:4" class="footnote-ref" role="doc-noteref">4</a></sup></p>
<p>Now we can open in Twine 2.</p>
<p>*edits*</p>
<p>How can we bring it back and save the changes, both layout and textual, to our VCS of choice?<br>
Not hard.</p>
<p><code>mv $/Documents/Twine/Stores/Fibres.html our/vcs/repo</code></p>
<p>And then update our source file.</p>
<p><code>tweego Fibres.html -d -o Fibres.twee</code></p>
<p>This is all rather straightforward. There is additional issue that Twine 2 creates: When <code>Fibres</code> archive was opened, Twine 2 saves an archive that uses the <code>StoryTitle</code> parameter. Which in this case wasn&rsquo;t <code>Fibres</code> but instead <code>Fibres[Part 1]</code>. Oops. Easy fix.</p>
<p>Now we&rsquo;re all happy. Generate the Twine 2 archive, copy to the Twine 2 story directory, work on the file, copy the file back and decode to Twee3 code. E.A.S.Y</p>
<h2 id="from-twine-generated-html-to-an-executable-in-the-year-of-our-lord-2020">From Twine generated html to an executable in the year of our lord 2020</h2>
<p>Hrmm, this was the hard part. Why? Because lots of different tools have lots of little issues that break. I will have nightmares about <code>ENOTDIR</code> for a while to come.<br>
The plan: make an executable of a Twine game to put on itch.io. I&rsquo;m aware I could deploy for web there (or quite frankly anywhere), but I want distributables because then a JS update won&rsquo;t come along and cripple it (a la <code>Awaken</code> on GameJolt until recently).</p>
<p><strong>Approach 1: Use someone else&rsquo;s Twine/HTML game tool.</strong><br>
Simples. There&rsquo;s a few listed. Some are very old and unmaintained. Some are overkill (one day I&rsquo;ll try you Cradle). A promising one called HTMLE exists. It however doesn&rsquo;t work nicely at uses a very old nw.js build. Not ideal.</p>
<p><strong>Approach 2: Do my own NW.js build</strong><br>
This did not look particularly fun and lots of people have moved away from NW.js to&hellip;</p>
<p><strong>Approach 3: Electron seems good. Let&rsquo;s use that</strong><br>
Twine 2 uses Electron, so if it&rsquo;s good enough for them, it&rsquo;s good enough for me.
Simplified creating of Electron apps is ironically not very simple due to NPM/NPX vs Yarn issues. Three main tools exist: <code>electron-packager</code>, <code>electron-builder</code>, and <code>electron-forge</code>. I tried them in this order. Why did I try 3? Because the first two kept throwing up either issues during build or execution of the final output. <code>electron-forge</code> however worked almost perfectly once I realised that I still had some stray .yarn directores and thus purged them.
So now I have a distributible Fibres. Yay! The goal reached!</p>
<p>Ha.</p>
<p>Can we include working audio in this app?<br>
Yep.</p>
<p>Oh good.</p>
<p><code>electron-forge</code> does require some boilerplate to be saved to make life easier. And thats the only addition to the repository. Excellent. Well, now we have a build script that moves stuff around so that out final executables contain everything and work correctly. Just need to remember to update that <code>packages.json</code> file every so often.</p>
<h2 id="the-full-workflow">The full workflow.</h2>
<h3 id="from-an-old-twine-1-game-to-a-stable-safe-twine-2-one-with-distributing">From an old Twine 1 game to a stable, safe Twine 2 one with distributing</h3>
<p>I think it&rsquo;s worth preserving, at least for my sake, how to do this. I have a LOT of Twine 1 files. There&rsquo;s a number of tools to be made from this, but I&rsquo;ll save that for a future bout of hypomania.</p>
<p>How does the directory in version control look now?</p>





<pre tabindex="0"><code>	/
	--src
        --audio
        --imgs
        index.html
        Fibres.twee
    --twine1
        Fibres.tws
        Fibres.tw2
    --dist
        --fibres
            -Package.json
            -**other stuff**
        Makefile</code></pre><p>Of course, saving audio and images to VCS is an issue because of size, so they currently remain in Dropbox. For lack of a VPS, this must be the way.</p>
<p>Whether or not this is helpful to anyone remains to be seen, but at least it is for me.</p>
<p>The links to the saving graces of the day:</p>
<ul>
<li>Tweego <a href="https://www.motoslave.net/tweego/">https://www.motoslave.net/tweego/</a></li>
<li>electron-forge <a href="https://github.com/electron-userland/electron-forge">https://github.com/electron-userland/electron-forge</a></li>
</ul>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>the author of it is rather important in the Twine scene so it was a bit of a shock.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a>&#160;<a href="#fnref1:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>I mean the downloaded Twine 2 still exists in a browser, but a steady Electron one at least.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:3">
<p>And is authored by the person that made the tool mentioned in <sup id="fnref1:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>&#160;<a href="#fnref:3" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:4">
<p>This if for *-nix systems. On Windows it is likely different. I will update once I move to Windows land for editing Twine files.&#160;<a href="#fnref:4" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    <item>
      <title>Tools for my own case</title>
      <link>https://lockeb.dev/posts/tools-for-my-own-case/</link>
      <pubDate>Fri, 31 Jan 2020 07:30:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/tools-for-my-own-case/</guid>
      <description>&lt;p&gt;This is hosted on Github Pages (edit: not after the migration).&#xA;I have 3 other sites hosted on neocities. They have a nice little tool (Neocities-CLI) that allows me to push stuff directly to the respective site directory.&lt;br&gt;&#xA;But Neocities-CLI only supports a /single/ site. I got bored today and decided to extend it to allow for infinite users. Following their practices, keys are in plaintext (yuck) but I can&amp;rsquo;t really think of another way to do it.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This is hosted on Github Pages (edit: not after the migration).
I have 3 other sites hosted on neocities. They have a nice little tool (Neocities-CLI) that allows me to push stuff directly to the respective site directory.<br>
But Neocities-CLI only supports a /single/ site. I got bored today and decided to extend it to allow for infinite users. Following their practices, keys are in plaintext (yuck) but I can&rsquo;t really think of another way to do it.</p>
<p>I&rsquo;ll eventually submit a pull request when I&rsquo;m happy with it.<br>
It was actually my first time writing in Ruby. But picking up new languages is easy.</p>
]]></content:encoded>
    </item>
    <item>
      <title>A Pointless Script</title>
      <link>https://lockeb.dev/posts/a-pointless-script/</link>
      <pubDate>Thu, 30 Jan 2020 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/a-pointless-script/</guid>
      <description>&lt;p&gt;I like making tools. That&amp;rsquo;s well known. I needed to do something that seems not very niche, so now there&amp;rsquo;s a script for it.&#xA;What did I need to do?&lt;br&gt;&#xA;Crop video, both in time and dimensions, rotate, and save as nice format.&lt;br&gt;&#xA;Why? To upload to services like Byte and Instagram (stories at least). It&amp;rsquo;s way nicer to do self-promotion if a) you don&amp;rsquo;t force people to rotate their device, and b) you provide a nicely focused bit of material for them.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I like making tools. That&rsquo;s well known. I needed to do something that seems not very niche, so now there&rsquo;s a script for it.
What did I need to do?<br>
Crop video, both in time and dimensions, rotate, and save as nice format.<br>
Why? To upload to services like Byte and Instagram (stories at least). It&rsquo;s way nicer to do self-promotion if a) you don&rsquo;t force people to rotate their device, and b) you provide a nicely focused bit of material for them.</p>
<p>I tried to make it as <code>bash</code> friendly as possible. The only weird tool it uses is <code>ffmpeg</code>. I should make a version for <code>mencoder</code> at some point.
The gist is here: <a href="https://gist.github.com/LockeBirdsey/9566de6787f87079df319c94f6592adc">https://gist.github.com/LockeBirdsey/9566de6787f87079df319c94f6592adc</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>What is this?</title>
      <link>https://lockeb.dev/posts/what-is-this/</link>
      <pubDate>Tue, 28 Jan 2020 16:16:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/what-is-this/</guid>
      <description>&lt;p&gt;This is the 100023rd blog I&amp;rsquo;ve set up. But this is nicer I think.&#xA;Getting back into putting dev stuff online and I&amp;rsquo;ll try putting it all here.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>This is the 100023rd blog I&rsquo;ve set up. But this is nicer I think.
Getting back into putting dev stuff online and I&rsquo;ll try putting it all here.</p>
]]></content:encoded>
    </item>
    <item>
      <title>So I Made Some Twitter Bots..</title>
      <link>https://lockeb.dev/posts/so-i-made-some-twitter-bots/</link>
      <pubDate>Wed, 08 Jan 2020 22:00:00 +0000</pubDate><author>byzxor@tuta.io (byzxor_)</author>
      <guid>https://lockeb.dev/posts/so-i-made-some-twitter-bots/</guid>
      <description>&lt;p&gt;I got rather bored last night and made some bots. I&amp;rsquo;ve been meaning to do this for &amp;gt; years.&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;Number 1: easy. Simple set of corpora, generate a (mostly) logical sentence and post.&lt;/li&gt;&#xA;&lt;li&gt;Number 2: less easy. Download tweets from x accounts, merge tweets, use a markov chain, generate shitposts.&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;p&gt;I think I have ideas for more. I have a weird idea for something as well.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I got rather bored last night and made some bots. I&rsquo;ve been meaning to do this for &gt; years.</p>
<ul>
<li>Number 1: easy. Simple set of corpora, generate a (mostly) logical sentence and post.</li>
<li>Number 2: less easy. Download tweets from x accounts, merge tweets, use a markov chain, generate shitposts.</li>
</ul>
<p>I think I have ideas for more. I have a weird idea for something as well.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
