<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>forbiddenlake</title>
    <link>https://blog.kiserai.net/</link>
    <description></description>
    <pubDate>Tue, 28 Apr 2026 11:56:34 +0000</pubDate>
    <item>
      <title>Private Exercise Tracking with Android, Tasker, OpenTracks, and FitTrackee</title>
      <link>https://blog.kiserai.net/private-exercise-tracking-with-android-tasker-opentracks-and-fittrackee</link>
      <description>&lt;![CDATA[Intro&#xA;&#xA;Recently I set up a private and self-hosted exercise tracker, like Strava but without sharing my data with them and their 700 advertising partners.&#xA;&#xA;OpenTracks is a sport tracking application that completely respects your privacy, and it&#39;s so private, that it doesn&#39;t even request Internet permissions, and can&#39;t upload to your Google Drive either.&#xA;&#xA;FitTrackee is a simple self-hosted, web-based, workout/activity tracker.&#xA;&#xA;OpenTracks can export activity records to a file, and FitTrackee can import them, but how can we automatically get the record from one to the other? This post is about doing that with Tasker.&#xA;&#xA;Task&#xA;&#xA;Tasker is a total automation app for Android and here I&#39;ll share the task I wrote to solve this problem. It watches a folder for the activity record, then uploads it over HTTPS.&#xA;&#xA;First, set OpenTracks to export a track to storage after recording is finished. For where, use a folder named Opentracks/ on the root of the filesystem.&#xA;&#xA;Then, import this profile and task.&#xA;&#xA;Then:&#xA;&#xA;Change the URL to that of your FitTrackee instance in 3 places.&#xA;Change the login email and password to that of your FitTrackee user.&#xA;If needed, change the folder the profile watches.&#xA;&#xA;Finally, try recording an activity with OpenTracks and opening FitTrackee.&#xA;&#xA;image]]&gt;</description>
      <content:encoded><![CDATA[<h2 id="intro">Intro</h2>

<p>Recently I set up a private and self-hosted exercise tracker, like Strava but without sharing my data with them and their 700 advertising partners.</p>

<p><a href="https://codeberg.org/OpenTracksApp/OpenTracks">OpenTracks</a> is a sport tracking application that completely respects your privacy, and it&#39;s so private, that it doesn&#39;t even request Internet permissions, and can&#39;t upload to your Google Drive either.</p>

<p><a href="https://github.com/SamR1/FitTrackee">FitTrackee</a> is a simple self-hosted, web-based, workout/activity tracker.</p>

<p>OpenTracks can export activity records to a file, and FitTrackee can import them, but how can we <strong>automatically</strong> get the record from one to the other? This post is about doing that with Tasker.</p>

<h2 id="task">Task</h2>

<p><a href="https://tasker.joaoapps.com/">Tasker</a> is a total automation app for Android and here I&#39;ll share the task I wrote to solve this problem. It watches a folder for the activity record, then uploads it over HTTPS.</p>

<p>First, set OpenTracks to export a track to storage after recording is finished. For where, use a folder named <code>Opentracks/</code> on the root of the filesystem.</p>

<p>Then, import <a href="https://taskernet.com/shares/?user=AS35m8no7xpg6%2BR1D4HOE1YaVRTxUwQ5WQgKbpLBGojqzOTOhXCnWCM2jo1BJYdzuC8%3D&amp;id=Profile%3ANew+Opentrack">this profile and task</a>.</p>

<p>Then:</p>
<ol><li>Change the URL to that of your FitTrackee instance in 3 places.</li>
<li>Change the login email and password to that of your FitTrackee user.</li>
<li>If needed, change the folder the profile watches.</li></ol>

<p>Finally, try recording an activity with OpenTracks and opening FitTrackee.</p>

<p><img src="https://dabor.kiserai.net/i/9005664a-c213-482c-9733-990d40b9462a.jpg" alt="image"></p>
]]></content:encoded>
      <guid>https://blog.kiserai.net/private-exercise-tracking-with-android-tasker-opentracks-and-fittrackee</guid>
      <pubDate>Fri, 20 Mar 2026 18:04:23 +0000</pubDate>
    </item>
    <item>
      <title>Elite: Dangerous HUD Mod UI on Linux</title>
      <link>https://blog.kiserai.net/elite-dangerous-hud-mod-ui-on-linux</link>
      <description>&lt;![CDATA[2025 update: With the release of version 3, none of the below is necessary. &#xA;&#xA;----&#xA;&#xA;EDHM+UI is a tool that lets you change the colors and lighting of the HUD in Elite: Dangerous.  Does it work on Linux? Yes!&#xA;&#xA;tl;dr: Install EDHM+UI in its own WINE prefix, then point it at your E:D install.&#xA;&#xA;!--more--&#xA;&#xA;Long version:&#xA;&#xA;Download the EDHM+UI installer (EDHMUISetup.msi) from GitHub.&#xA;Choose a name for a new WINE prefix: export WINEPREFIX=&#34;$HOME/.wineedhmui&#34;&#xA;Initialize the prefix with: wine wineboot&#xA;Install .NET to the prefix: winetricks dotnet48. This will take you through a couple installers. Just continue through any warnings the installers show.&#xA;Make sure the Windows version is set to one supported by EDHM+UI: winetricks win10&#xA;Install EDHM+UI to the prefix (replace with the path to the .msi if it is not in the current folder): wine msiexec /i ./EDHMUISetup.msi&#xA;(Optional) Download an icon for a shortcut: wget https://bluemystical.github.io/edhm-api/assets/img/logo.png -O &#34;${WINEPREFIX}/logo.png&#34;&#xA;Set up a .desktop file to put EDHM in your menu.  Create ~/.local/share/applications/edhm-ui.desktop with a text editor and put the following in. Replace NAME with your username.&#xA;[Desktop Entry]&#xA;Name=EDHM UI&#xA;Comment=E:D HUD Mod UI&#xA;Exec=env WINEDEBUG=&#34;-all&#34; WINEPREFIX=&#34;/home/NAME/.wineedhmui&#34; &#34;/home/NAME/.wineedhmui/drivec/users/NAME/AppData/Local/EDHMUI/EDHMUImk2.exe&#34;&#xA;Icon=/home/NAME/.wineedhmui/logo.png&#xA;Terminal=false&#xA;Type=Application&#xA;Categories=Game&#xA;&#xA;Start EDHM+UI. Point it at your Elite Dangerous install(s). In the following picture it references my Steam install. You can likely find your install with: find ~ -name elite-dangerous-odyssey-64, but be sure to use the Windows-style path like I do, usually under Z:\. To make the box editable/browsable, CTRL+LEFT-CLICK the pi (π) symbol first.&#xA;image&#xA;You can then use EDHM+UI like on Windows. Select a premade theme, tweak it, add third-party plugins, and apply it. And just like Windows, you can use a hotkey (F11 by default) to reload a changed theme while the game is running.  &#xA;&#xA;Note: I was getting frequent crashes from EDHM UI, but I was still able to apply a theme and add a third-party plugin. &#xA;&#xA;---&#xA;References:&#xA;EDHM+UI Discord MrVaad&#xA;EDHM+UI Discord Thorned Rose&#xA;GitHub issue&#xA;&#xA;---&#xA;Tested versions:&#xA;Arch Linux as of 2024-02-19&#xA;wine 9.2-1&#xA;winetricks 20240105-1&#xA;EDHM+UI v2.2.19&#xA;---&#xA;Filed in: #elitedangerous #linux]]&gt;</description>
      <content:encoded><![CDATA[<p><strong>2025 update</strong>: With the <a href="https://github.com/BlueMystical/EDHM_UI/releases">release of version 3</a>, none of the below is necessary.</p>

<hr>

<p><a href="https://bluemystical.github.io/edhm-api/">EDHM+UI</a> is a tool that lets you change the colors and lighting of the HUD in Elite: Dangerous.  Does it work on Linux? Yes!</p>

<p>tl;dr: Install EDHM+UI in its <em>own</em> WINE prefix, then point it at your E:D install.</p>



<p>Long version:</p>
<ol><li>Download the EDHM+UI installer (<code>EDHM_UI_Setup.msi</code>) from <a href="https://github.com/BlueMystical/EDHM_UI/releases/latest">GitHub</a>.</li>
<li>Choose a name for a new WINE prefix: <code>export WINEPREFIX=&#34;$HOME/.wine_edhmui&#34;</code></li>
<li>Initialize the prefix with: <code>wine wineboot</code></li>
<li>Install .NET to the prefix: <code>winetricks dotnet48</code>. This will take you through a couple installers. Just continue through any warnings the installers show.</li>
<li>Make sure the Windows version is set to one supported by EDHM+UI: <code>winetricks win10</code></li>
<li>Install EDHM+UI to the prefix (replace with the path to the .msi if it is not in the current folder): <code>wine msiexec /i ./EDHM_UI_Setup.msi</code></li>
<li>(Optional) Download an icon for a shortcut: <code>wget https://bluemystical.github.io/edhm-api/assets/img/logo.png -O &#34;${WINEPREFIX}/logo.png&#34;</code></li>

<li><p>Set up a .desktop file to put EDHM in your menu.  Create <code>~/.local/share/applications/edhm-ui.desktop</code> with a text editor and put the following in. Replace NAME with your username.</p>

<pre><code class="language-sh">[Desktop Entry]
Name=EDHM UI
Comment=E:D HUD Mod UI
Exec=env WINEDEBUG=&#34;-all&#34; WINEPREFIX=&#34;/home/NAME/.wine_edhmui&#34; &#34;/home/NAME/.wine_edhmui/drive_c/users/NAME/AppData/Local/EDHM_UI/EDHM_UI_mk2.exe&#34;
Icon=/home/NAME/.wine_edhmui/logo.png
Terminal=false
Type=Application
Categories=Game
</code></pre></li>

<li><p>Start EDHM+UI. Point it at your Elite Dangerous install(s). In the following picture it references my Steam install. You can likely find your install with: <code>find ~ -name elite-dangerous-odyssey-64</code>, but be sure to use the Windows-style path like I do, usually under <code>Z:\</code>. <strong>To make the box editable/browsable, CTRL+LEFT-CLICK the pi (π) symbol first.</strong>
<img src="https://dabor.kiserai.net/i/fcd388e2-095f-4c41-87ff-69676bae4246.jpg" alt="image"></p></li>

<li><p>You can then use EDHM+UI like on Windows. Select a premade theme, tweak it, add third-party plugins, and apply it. And just like Windows, you can use a hotkey (F11 by default) to reload a changed theme <em>while the game is running</em>.</p></li></ol>

<p><strong>Note</strong>: I was getting frequent crashes from EDHM UI, but I was still able to apply a theme and add a third-party plugin.</p>

<hr>

<p>References:
1. <a href="https://discord.com/channels/773552741632180224/773553131568889916/1171209291856883773">EDHM+UI Discord MrVaad</a>
2. <a href="https://discord.com/channels/773552741632180224/773553131568889916/1016666369774858240">EDHM+UI Discord Thorned Rose</a>
3. <a href="https://github.com/BlueMystical/EDHM_UI/issues/36#issuecomment-1595329861">GitHub issue</a></p>

<hr>

<p>Tested versions:
* Arch Linux as of 2024-02-19
* wine 9.2-1
* winetricks 20240105-1
* EDHM+UI v2.2.19</p>

<hr>

<p>Filed in: <a href="https://blog.kiserai.net/tag:elitedangerous" class="hashtag"><span>#</span><span class="p-category">elitedangerous</span></a> <a href="https://blog.kiserai.net/tag:linux" class="hashtag"><span>#</span><span class="p-category">linux</span></a></p>
]]></content:encoded>
      <guid>https://blog.kiserai.net/elite-dangerous-hud-mod-ui-on-linux</guid>
      <pubDate>Wed, 21 Feb 2024 17:17:07 +0000</pubDate>
    </item>
    <item>
      <title>Scheduled Game Save Backups with Ludusavi on Linux</title>
      <link>https://blog.kiserai.net/scheduled-game-save-backups-with-ludusavi-on-linux</link>
      <description>&lt;![CDATA[Ludusavi is a cross-platform tool for backing up game saves and configuration.  Currently, it does not have a built-in way to schedule backups, but we can use system tools to do so instead. In the post, we will use systemd user timers.&#xA;&#xA;!--more--&#xA;The following steps make a couple assumptions:&#xA;&#xA;You are running Linux and using systemd&#xA;The ludusavi command is available at /usr/bin/ludusavi, which it is at least for the Arch Linux AUR package.  You may need to adjust it when using another distribution or package.&#xA;The timer is set to run daily, or 5-10 minutes after boot. You can adjust it if you want.&#xA;&#xA;Steps&#xA;&#xA;1\. Set Ludusavi up in the GUI as you wish. Test with the Preview and Back Up buttons.&#xA;2\. Create a service with systemctl edit --user --force --full ludusavi-backup.service and put the following text in it:&#xA;&#xA;[Unit]&#xA;Description=Back up game saves&#xA;After=network.target&#xA;&#xA;[Service]&#xA;Type=oneshot&#xA;ExecStart=/usr/bin/ludusavi backup --force&#xA;&#xA;[Install]&#xA;WantedBy=default.target&#xA;&#xA;3\. Create a timer with systemctl edit --user --force --full ludusavi-backup.timer and put the following text in it:&#xA;&#xA;[Unit]&#xA;Description=Back up game saves&#xA;RefuseManualStart=no&#xA;RefuseManualStop=no&#xA;&#xA;[Timer]&#xA;OnCalendar=daily&#xA;RandomizedDelaySec=5min&#xA;OnBootSec=5min&#xA;&#xA;[Install]&#xA;WantedBy=timers.target&#xA;&#xA;4\. Enable the timer and run the backup with: systemctl --user enable --now ludusavi-backup.timer&#xA;&#xA;Other Commands&#xA;&#xA;List timers: systemctl --user list-timers --all&#xA;Run a backup manually: systemctl --user start ludusavi-backup.service&#xA;Check logs: journalctl --user -u ludusavi-backup.service&#xA;&#xA;Filed in: #linux]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://github.com/mtkennerly/ludusavi">Ludusavi</a> is a cross-platform tool for backing up game saves and configuration.  Currently, it does not have a built-in way to schedule backups, but we can use system tools to do so instead. In the post, we will use <strong>systemd user timers</strong>.</p>



<p>The following steps make a couple assumptions:</p>
<ol><li>You are running Linux and using systemd</li>
<li>The ludusavi command is available at <code>/usr/bin/ludusavi</code>, which it is at least for the Arch Linux <a href="https://aur.archlinux.org/packages/ludusavi">AUR package</a>.  You may need to adjust it when using another distribution or package.</li>
<li>The timer is set to run daily, or 5-10 minutes after boot. You can <a href="https://www.freedesktop.org/software/systemd/man/latest/systemd.timer.html">adjust it if you want</a>.</li></ol>

<h2 id="steps">Steps</h2>

<p>1. Set Ludusavi up in the GUI as you wish. Test with the Preview and Back Up buttons.
2. Create a service with <code>systemctl edit --user --force --full ludusavi-backup.service</code> and put the following text in it:</p>

<pre><code class="language-ini">[Unit]
Description=Back up game saves
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/bin/ludusavi backup --force

[Install]
WantedBy=default.target
</code></pre>

<p>3. Create a timer with <code>systemctl edit --user --force --full ludusavi-backup.timer</code> and put the following text in it:</p>

<pre><code class="language-ini">[Unit]
Description=Back up game saves
RefuseManualStart=no
RefuseManualStop=no

[Timer]
OnCalendar=daily
RandomizedDelaySec=5min
OnBootSec=5min

[Install]
WantedBy=timers.target
</code></pre>

<p>4. Enable the timer and run the backup with: <code>systemctl --user enable --now ludusavi-backup.timer</code></p>

<h2 id="other-commands">Other Commands</h2>
<ul><li>List timers: <code>systemctl --user list-timers --all</code></li>
<li>Run a backup manually: <code>systemctl --user start ludusavi-backup.service</code></li>
<li>Check logs: <code>journalctl --user -u ludusavi-backup.service</code></li></ul>

<p>Filed in: <a href="https://blog.kiserai.net/tag:linux" class="hashtag"><span>#</span><span class="p-category">linux</span></a></p>
]]></content:encoded>
      <guid>https://blog.kiserai.net/scheduled-game-save-backups-with-ludusavi-on-linux</guid>
      <pubDate>Mon, 04 Dec 2023 17:17:21 +0000</pubDate>
    </item>
    <item>
      <title>Hardening Tailscale on Arch Linux: Polkit   = 106</title>
      <link>https://blog.kiserai.net/hardening-tailscale-on-arch-linux-polkit-106</link>
      <description>&lt;![CDATA[Tailscale is an easy and free service for creating your own mesh VPN, built on Wireguard and easier to scale.  Tailscale does provide instructions for hardening it - reducing its privileges to the minimum necessary to run.  However, the instructions don&#39;t fully work for Linux distributions running polkit   = 106, like Arch Linux.&#xA;&#xA;!--more--&#xA;&#xA;Solution&#xA;&#xA;The solution I came up with is, instead of using the Tailscale-provided polkit configuration, create /etc/polkit-1/rules.d/99-tailscaled-dns.rules with the following content:&#xA;&#xA;polkit.addRule(function(action, subject) {&#xA;    if (action.id.startsWith(&#34;org.freedesktop.resolve1.&#34;) &amp;&amp;&#xA;        subject.user == &#34;tailscaled&#34;)&#xA;    {&#xA;        return polkit.Result.YES;&#xA;    }&#xA;});&#xA;&#xA;Then restart it with sudo systemctl restart polkit.service .&#xA;&#xA;I have filed #9344 and hope the official documentation will be updated soon, as Ubuntu 23.10 and later have finally updated polkitd.&#xA;&#xA;Filed in: #linux]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://tailscale.com/">Tailscale</a> is an easy and free service for creating your own mesh VPN, built on <a href="https://www.wireguard.com/">Wireguard</a> and easier to scale.  Tailscale does provide <a href="https://tailscale.com/kb/1279/security-node-hardening/">instructions</a> for hardening it – reducing its privileges to the minimum necessary to run.  However, the instructions don&#39;t fully work for Linux distributions running <a href="https://discourse.ubuntu.com/t/use-of-javascript-rules-in-polkit/13892">polkit &gt;= 106</a>, like Arch Linux.</p>



<h1 id="solution">Solution</h1>

<p>The solution I came up with is, instead of using the Tailscale-provided polkit configuration, create <code>/etc/polkit-1/rules.d/99-tailscaled-dns.rules</code> with the following content:</p>

<pre><code class="language-javascript">polkit.addRule(function(action, subject) {
    if (action.id.startsWith(&#34;org.freedesktop.resolve1.&#34;) &amp;&amp;
        subject.user == &#34;tailscaled&#34;)
    {
        return polkit.Result.YES;
    }
});
</code></pre>

<p>Then restart it with <code>sudo systemctl restart polkit.service</code> .</p>

<p>I have filed <a href="https://github.com/tailscale/tailscale/issues/9344">#9344</a> and hope the official documentation will be updated soon, as Ubuntu 23.10 and later have finally updated polkitd.</p>

<p>Filed in: <a href="https://blog.kiserai.net/tag:linux" class="hashtag"><span>#</span><span class="p-category">linux</span></a></p>
]]></content:encoded>
      <guid>https://blog.kiserai.net/hardening-tailscale-on-arch-linux-polkit-106</guid>
      <pubDate>Tue, 24 Oct 2023 17:56:24 +0000</pubDate>
    </item>
    <item>
      <title>Save Your Stellaris Mod Playset Before a Game Update</title>
      <link>https://blog.kiserai.net/save-your-stellaris-mod-playset-before-a-game-update</link>
      <description>&lt;![CDATA[Game updates frequently break mods, and mod updates often break your saved multiplayer games because players don&#39;t reliably get them at the same time.  Here is how to use Irony Mod Manager to create a stable, unchanging mod pack. You can combine it with the Steam beta menu to have an unchanging checksum that will always work with the version of the game it was made for.&#xA;&#xA;!--more--&#xA;&#xA;Step 1: Make your mod playset as usual&#xA;&#xA;In the Paradox launcher (or Irony if you already use it), set up your mods in a playset as usual, and test them out ingame. This is the most important step, because once we&#39;re done, it will be difficult to change.  &#xA;&#xA;Each mod should list its recommended load order in its description, but if you need tips for setting a load order, the wiki has guidelines here.&#xA;&#xA;Step 2: Get Irony Mod Manager&#xA;&#xA;Download and install Irony. Instructions are on the linked page.&#xA;&#xA;Step 3: Create a merged mod&#xA;&#xA;Import your playset&#xA;&#xA;Open up Irony Mod Manager.&#xA;&#xA;If you are an Irony user already, then select your collection.&#xA;&#xA;Otherwise, for Paradox launcher users, make sure your desired playset is selected in the Paradox launcher, then close it.&#xA;&#xA;Then in Irony, import from the launcher: In the top middle, click the three-dot menu next to Import, and select Import From Paradox Launcher.&#xA;&#xA;Import menu in Irony&#xA;&#xA;Merge your playset&#xA;&#xA;Click Merge in the top right, then select Basic. Irony will create one local megamod containing the files from all mods in your playset.&#xA;&#xA;Merge menu in Irony&#xA;&#xA;  Aside: Merge Compress&#xA;  If you will not be uploading this merged mod, then you can select Compress instead. The game usually loads compressed mods faster, but this will create a compressed local copy of every mod in the playset. More info can be found in the Irony documentation.&#xA;&#xA;  Aside: Resolving Conflicts&#xA;  I do not recommend resolving mod conflicts in Irony unless you are an experienced modder.  A conflict is not necessarily a bug, and properly resolving conflicts requires in-depth knowledge of modding Stellaris and of the mods that are conflicting.  There&#39;s no point in clicking Resolve without thought. The easier way to resolve conflicts is by not using conflicting mods, or by setting your load order properly.&#xA;&#xA;Tada!&#xA;&#xA;Back in the Paradox launcher, you may now select your merged mod in your playset like any other mod. It will be named the same as your existing playset with (Merged) prepended. I recommend adding it to a new playset by itself and naming the playset after the current game version.&#xA;&#xA;Paradox launcher menu of All Installed Mods&#xA;&#xA;Step 4: Upload to Steam (optional - for multiplayer games)&#xA;&#xA;Upload your merged mod to Steam. More info on the Stellaris WIki.&#xA;Steam mod upload dialog.&#xA;Change the visibility on your mod to unlisted/friends only.&#xA;Give your friends the link and have them subscribe.&#xA;Make a playset containing only your own local copy of the merged mod. Your friends should make a playset containing only the Steam Workshop upload.&#xA;Congrats, the checksum will never change!&#xA;&#xA;  Aside: Don&#39;t subscribe to your own mod on the workshop! (from the Stellaris Modding Den):&#xA;  If your mod doesn&#39;t seem to be having any effect, this is often caused by a common beginner mistake: subscribing on the workshop to a mod you have in your local files. This will cause the game to ignore the workshop version, and only the local version will work. Avoid subscribing to your own mod - if the version you uploaded works, the workshop version will work. Alternatively, if you must test it, change the name of your local mod in the descriptor file. This will allow you to subscribe to the workshop version separately.&#xA;&#xA;Step 5: Revert to a previous version (optional - after the game updates)&#xA;&#xA;Paradox provides the ability to revert to many previous game versions via the Steam Beta menu. After a new game version releases, if you want to go back and use the merged mod you created, this is where you go back to the game version it worked with.&#xA;&#xA;Steam Beta Menu&#xA;&#xA;Filed in: #stellaris]]&gt;</description>
      <content:encoded><![CDATA[<p>Game updates frequently break mods, and mod updates often break your saved multiplayer games because players don&#39;t reliably get them at the same time.  Here is how to use Irony Mod Manager to create a stable, unchanging mod pack. You can combine it with the Steam beta menu to have an unchanging checksum that will always work with the version of the game it was made for.</p>



<h2 id="step-1-make-your-mod-playset-as-usual">Step 1: Make your mod playset as usual</h2>

<p>In the Paradox launcher (or Irony if you already use it), set up your mods in a playset as usual, and test them out ingame. This is the most important step, because once we&#39;re done, it will be difficult to change.</p>

<p>Each mod should list its recommended load order in its description, but if you need tips for setting a load order, the wiki has guidelines <a href="https://stellaris.paradoxwikis.com/Modding#Mod_load_order">here</a>.</p>

<h2 id="step-2-get-irony-mod-manager">Step 2: Get Irony Mod Manager</h2>

<p>Download and install <a href="https://github.com/bcssov/IronyModManager/releases">Irony</a>. Instructions are on the linked page.</p>

<h2 id="step-3-create-a-merged-mod">Step 3: Create a merged mod</h2>

<h3 id="import-your-playset">Import your playset</h3>

<p>Open up Irony Mod Manager.</p>

<p>If you are an Irony user already, then select your collection.</p>

<p>Otherwise, for <strong>Paradox launcher</strong> users, make sure your desired playset is selected in the Paradox launcher, then close it.</p>

<p>Then in Irony, import from the launcher: In the top middle, click the three-dot menu next to Import, and select Import From Paradox Launcher.</p>

<p><img src="https://dabor.kiserai.net/i/c6ae3c0c-e6ec-4e5c-9258-d3f872ad5c3c.jpg" alt="Import menu in Irony"></p>

<h3 id="merge-your-playset">Merge your playset</h3>

<p>Click Merge in the top right, then select Basic. Irony will create one local megamod containing the files from all mods in your playset.</p>

<p><img src="https://dabor.kiserai.net/i/61e5a5a2-235e-4e00-81ff-e4be5d6aac4b.jpg" alt="Merge menu in Irony"></p>

<blockquote><p><strong>Aside</strong>: <em>Merge Compress</em>
If you will not be uploading this merged mod, then you can select Compress instead. The game usually loads compressed mods faster, but this will create a compressed local copy of <em>every</em> mod in the playset. More info can be found in the <a href="https://github.com/bcssov/IronyModManager/wiki/Collection-Mods">Irony documentation</a>.</p>

<p><strong>Aside</strong>: <em>Resolving Conflicts</em>
I do <em>not</em> recommend resolving mod conflicts in Irony unless you are an experienced modder.  A conflict is not necessarily a bug, and <em>properly</em> resolving conflicts requires in-depth knowledge of modding Stellaris and of the mods that are conflicting.  There&#39;s no point in clicking Resolve without thought. The easier way to resolve conflicts is by not using conflicting mods, or by setting your load order properly.</p></blockquote>

<h3 id="tada">Tada!</h3>

<p>Back in the Paradox launcher, you may now select your merged mod in your playset like any other mod. It will be named the same as your existing playset with <code>(Merged)</code> prepended. I recommend adding it to a new playset by itself and naming the playset after the current game version.</p>

<p><img src="https://dabor.kiserai.net/i/544ad6ad-29a2-4301-b489-5943a402f942.jpg" alt="Paradox launcher menu of All Installed Mods"></p>

<h2 id="step-4-upload-to-steam-optional-for-multiplayer-games">Step 4: Upload to Steam (optional – for multiplayer games)</h2>
<ol><li>Upload your merged mod to Steam. More info on the <a href="https://stellaris.paradoxwikis.com/Steam_Workshop#Uploading_a_mod">Stellaris WIki</a>.
<img src="https://dabor.kiserai.net/i/b4c58365-f69e-456b-b4b2-f4e49dce026a.jpg" alt="Steam mod upload dialog">.</li>
<li>Change the visibility on your mod to unlisted/friends only.</li>
<li>Give your friends the link and have them subscribe.</li>
<li>Make a playset containing only your own local copy of the merged mod. Your friends should make a playset containing only the Steam Workshop upload.</li>
<li>Congrats, the checksum will never change!</li></ol>

<blockquote><p><strong>Aside</strong>: <em>Don&#39;t subscribe to your own mod</em> on the workshop! (from the Stellaris Modding Den):
If your mod doesn&#39;t seem to be having any effect, this is often caused by a common beginner mistake: subscribing on the workshop to a mod you have in your local files. This will cause the game to ignore the workshop version, and only the local version will work. Avoid subscribing to your own mod – if the version you uploaded works, the workshop version will work. Alternatively, if you must test it, change the name of your local mod in the descriptor file. This will allow you to subscribe to the workshop version separately.</p></blockquote>

<h2 id="step-5-revert-to-a-previous-version-optional-after-the-game-updates">Step 5: Revert to a previous version (optional – after the game updates)</h2>

<p>Paradox provides the ability to revert to many previous game versions via the Steam Beta menu. After a new game version releases, if you want to go back and use the merged mod you created, this is where you go back to the game version it worked with.</p>

<p><img src="https://dabor.kiserai.net/i/2375d38d-a44c-4e05-a8ac-6e2626a747e9.jpg" alt="Steam Beta Menu"></p>

<p>Filed in: <a href="https://blog.kiserai.net/tag:stellaris" class="hashtag"><span>#</span><span class="p-category">stellaris</span></a></p>
]]></content:encoded>
      <guid>https://blog.kiserai.net/save-your-stellaris-mod-playset-before-a-game-update</guid>
      <pubDate>Wed, 06 Sep 2023 14:11:30 +0000</pubDate>
    </item>
    <item>
      <title>Crafting a DNS-over-HTTPS GET request manually</title>
      <link>https://blog.kiserai.net/crafting-a-dns-over-https-get-request-manually</link>
      <description>&lt;![CDATA[Let&#39;s say I want to create an external health check for AdGuard that exercises both the HTTP interface and the DNS resolution, because I do.  Unlike Cloudflare, AdGuard doesn&#39;t take an easy name parameter, and I found it quite difficult to find existing documentation on how to craft a DoH request manually. Here&#39;s how to do it in Python.&#xA;&#xA;!--more--&#xA;&#xA;Requirements&#xA;&#xA;Python 3&#xA;Ideally dnspython   = 2.2.0 (so, Ubuntu 22.04&#39;s python3-dnspython package will not work. Use pip or a python docker image). Earlier versions will work without setting id=0.&#xA;requests for testing&#xA;&#xA;One-liner&#xA;&#xA;Change example.com:&#xA;&#xA;DOMAIN=&#34;example.com&#34; python3 -c &#34;import os, dns.message, requests, base64; req = dns.message.makequery(os.environ[&#39;DOMAIN&#39;], &#39;A&#39;, id=0).towire(); print(base64.urlsafeb64encode(req).decode(&#39;utf-8&#39;).rstrip(&#39;=&#39;))&#34;&#xA;&#xA;Script&#xA;&#xA;Set DOMAIN environment variable before running:&#xA;&#xA;import os&#xA;import dns.message&#xA;import requests&#xA;import base64&#xA;&#xA;reqraw = dns.message.makequery(os.environ[&#39;DOMAIN&#39;], &#39;A&#39;, id=0).towire()&#xA;reqstr = base64.urlsafeb64encode(reqraw).decode(&#39;utf-8&#39;).rstrip(&#39;=&#39;)&#xA;print(&#34;Query path and encoded string to use with a GET request to a DNS-over-HTTPS server:&#34;)&#xA;print(&#34;/dns-query?dns=&#34; + reqstr)&#xA;print(&#34;\nTesting query with Cloudflare...&#34;)&#xA;resp = requests.get(&#34;https://cloudflare-dns.com/dns-query?dns=&#34; + reqstr)&#xA;resp.raiseforstatus()&#xA;msg = dns.message.from_wire(resp.content)&#xA;print(&#34;DNS response:&#34;)&#xA;print(msg)&#xA;&#xA;Example output&#xA;&#xA;$ DOMAIN=example.com python3 ./doh.py&#xA;Query path and encoded string to use with a GET request to a DNS-over-HTTPS server:&#xA;/dns-query?dns=AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE&#xA;&#xA;Testing query with Cloudflare...&#xA;DNS response:&#xA;id 0&#xA;opcode QUERY&#xA;rcode NOERROR&#xA;flags QR RD RA&#xA;;QUESTION&#xA;example.com. IN A&#xA;;ANSWER&#xA;example.com. 82324 IN A 93.184.216.34&#xA;;AUTHORITY&#xA;;ADDITIONAL&#xA;&#xA;References&#xA;&#xA;https://github.com/dohwg/draft-ietf-doh-dns-over-https/issues/30#issuecomment-345850479&#xA;&#xA;https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/make-api-requests/dns-wireformat/&#xA;&#xA;https://datatracker.ietf.org/doc/html/rfc8484#section-4.1&#xA;&#xA;Filed in: #python #dns #adguard]]&gt;</description>
      <content:encoded><![CDATA[<p>Let&#39;s say I want to create an external health check for <a href="https://adguard.com/en/welcome.html">AdGuard</a> that exercises both the HTTP interface and the DNS resolution, because I do.  Unlike <a href="https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/make-api-requests/">Cloudflare</a>, AdGuard doesn&#39;t take an easy <code>name</code> parameter, and I found it quite difficult to find existing documentation on how to craft a DoH request manually. Here&#39;s how to do it in Python.</p>



<h2 id="requirements">Requirements</h2>
<ul><li>Python 3</li>
<li>Ideally <code>dnspython</code> &gt;= 2.2.0 (so, Ubuntu 22.04&#39;s <code>python3-dnspython</code> package will not work. Use pip or a <a href="https://hub.docker.com/_/python">python docker image</a>). Earlier versions will work without setting <code>id=0</code>.</li>
<li><code>requests</code> for testing</li></ul>

<h2 id="one-liner">One-liner</h2>

<p>Change <code>example.com</code>:</p>

<pre><code class="language-bash">DOMAIN=&#34;example.com&#34; python3 -c &#34;import os, dns.message, requests, base64; req = dns.message.make_query(os.environ[&#39;DOMAIN&#39;], &#39;A&#39;, id=0).to_wire(); print(base64.urlsafe_b64encode(req).decode(&#39;utf-8&#39;).rstrip(&#39;=&#39;))&#34;
</code></pre>

<h2 id="script">Script</h2>

<p>Set DOMAIN environment variable before running:</p>

<pre><code class="language-python">import os
import dns.message
import requests
import base64

req_raw = dns.message.make_query(os.environ[&#39;DOMAIN&#39;], &#39;A&#39;, id=0).to_wire()
req_str = base64.urlsafe_b64encode(req_raw).decode(&#39;utf-8&#39;).rstrip(&#39;=&#39;)
print(&#34;Query path and encoded string to use with a GET request to a DNS-over-HTTPS server:&#34;)
print(&#34;/dns-query?dns=&#34; + req_str)
print(&#34;\nTesting query with Cloudflare...&#34;)
resp = requests.get(&#34;https://cloudflare-dns.com/dns-query?dns=&#34; + req_str)
resp.raise_for_status()
msg = dns.message.from_wire(resp.content)
print(&#34;DNS response:&#34;)
print(msg)
</code></pre>

<h2 id="example-output">Example output</h2>

<pre><code class="language-bash">$ DOMAIN=example.com python3 ./doh.py
Query path and encoded string to use with a GET request to a DNS-over-HTTPS server:
/dns-query?dns=AAABAAABAAAAAAAAB2V4YW1wbGUDY29tAAABAAE

Testing query with Cloudflare...
DNS response:
id 0
opcode QUERY
rcode NOERROR
flags QR RD RA
;QUESTION
example.com. IN A
;ANSWER
example.com. 82324 IN A 93.184.216.34
;AUTHORITY
;ADDITIONAL
</code></pre>

<h2 id="references">References</h2>

<p><a href="https://github.com/dohwg/draft-ietf-doh-dns-over-https/issues/30#issuecomment-345850479">https://github.com/dohwg/draft-ietf-doh-dns-over-https/issues/30#issuecomment-345850479</a></p>

<p><a href="https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/make-api-requests/dns-wireformat/">https://developers.cloudflare.com/1.1.1.1/encryption/dns-over-https/make-api-requests/dns-wireformat/</a></p>

<p><a href="https://datatracker.ietf.org/doc/html/rfc8484#section-4.1">https://datatracker.ietf.org/doc/html/rfc8484#section-4.1</a></p>

<p>Filed in: <a href="https://blog.kiserai.net/tag:python" class="hashtag"><span>#</span><span class="p-category">python</span></a> <a href="https://blog.kiserai.net/tag:dns" class="hashtag"><span>#</span><span class="p-category">dns</span></a> <a href="https://blog.kiserai.net/tag:adguard" class="hashtag"><span>#</span><span class="p-category">adguard</span></a></p>
]]></content:encoded>
      <guid>https://blog.kiserai.net/crafting-a-dns-over-https-get-request-manually</guid>
      <pubDate>Mon, 21 Aug 2023 19:57:41 +0000</pubDate>
    </item>
    <item>
      <title>Final Fantasy 14 Battle Effects Macro</title>
      <link>https://blog.kiserai.net/final-fantasy-14-battle-effects-macro</link>
      <description>&lt;![CDATA[Originally posted on reddit.&#xA;&#xA;The following macro will:&#xA;&#xA;Make every summoner summon small on your screen (this is a client-side setting)&#xA;Keep limited party effects (bubbles, etc)&#xA;Turn off effects outside your party&#xA;Also turn down sound effects&#xA;&#xA;Add this macro and the second one to a bar if you want to toggle back and forth.&#xA;&#xA;!--more--&#xA;&#xA;THAL&#39;S BALLS, MAN, I CAN&#39;T SEE ANYTHING macro:&#xA;&#xA;    /micon &#34;shut eyes&#34; emote&#xA;    /bfx party simple&#xA;    /bfx other off&#xA;    /petsize all small&#xA;    /soundeffectsparty 50&#xA;    /soundeffectsother 20&#xA;&#xA;Use the following to turn it all back up:&#xA;&#xA;ON SECOND THOUGHT I WANT TO GO BLIND macro:&#xA;&#xA;    /micon &#34;Examine Self&#34; emote&#xA;    /bfx party all&#xA;    /bfx other all&#xA;    /petsize all large&#xA;    /soundeffectsparty 100&#xA;    /soundeffectsother 100&#xA;&#xA;Command reference:&#xA;&#xA;/petsize&#xA;/bfx&#xA;&#xA;Filed in: #ffxiv]]&gt;</description>
      <content:encoded><![CDATA[<p>Originally posted on <a href="https://www.reddit.com/r/ffxiv/comments/s3y7rp/titans_arse_too_big_for_you_holy_hurting_your/">reddit</a>.</p>

<p>The following macro will:</p>
<ul><li>Make every summoner summon small on your screen (this is a <em>client-side</em> setting)</li>
<li><em>Keep</em> limited party effects (bubbles, etc)</li>
<li>Turn off effects outside your party</li>
<li>Also turn down sound effects</li></ul>

<p>Add this macro and the second one to a bar if you want to toggle back and forth.</p>



<h2 id="thal-s-balls-man-i-can-t-see-anything-macro">THAL&#39;S BALLS, MAN, I CAN&#39;T SEE ANYTHING macro:</h2>

<pre><code>    /micon &#34;shut eyes&#34; emote
    /bfx party simple
    /bfx other off
    /petsize all small
    /soundeffectsparty 50
    /soundeffectsother 20
</code></pre>

<p>Use the following to turn it all back up:</p>

<h2 id="on-second-thought-i-want-to-go-blind-macro">ON SECOND THOUGHT I WANT TO GO BLIND macro:</h2>

<pre><code>    /micon &#34;Examine Self&#34; emote
    /bfx party all
    /bfx other all
    /petsize all large
    /soundeffectsparty 100
    /soundeffectsother 100
</code></pre>

<p>Command reference:</p>
<ul><li><a href="https://na.finalfantasyxiv.com/lodestone/playguide/db/text_command/ded8f6e43d6/">/petsize</a></li>
<li><a href="https://na.finalfantasyxiv.com/lodestone/playguide/db/text_command/9241c2b27da/">/bfx</a></li></ul>

<p>Filed in: <a href="https://blog.kiserai.net/tag:ffxiv" class="hashtag"><span>#</span><span class="p-category">ffxiv</span></a></p>
]]></content:encoded>
      <guid>https://blog.kiserai.net/final-fantasy-14-battle-effects-macro</guid>
      <pubDate>Sun, 20 Aug 2023 21:00:44 +0000</pubDate>
    </item>
    <item>
      <title>Zabbix Web interface with LLDAP</title>
      <link>https://blog.kiserai.net/zabbix-web-interface-with-lldap</link>
      <description>&lt;![CDATA[I wrote a document for configuring Zabbix 6.0 web interface to use LLDAP for logins. Here is the same information, with pictures.&#xA;&#xA;!--more--&#xA;&#xA;This example is for the Zabbix Web interface version 6.0, which is the supported LTS version as of August 2023.  Later versions have additional options.&#xA;&#xA;For the associated 6.0 documentation see here and for the current manual see here.&#xA;&#xA;Note that an LDAP user must exist in Zabbix Web as well, however its Zabbix password will not be used. When creating the user in Zabbix, the user should also be added to your desired Zabbix roles/groups.&#xA;&#xA;Configure LDAP Settings&#xA;&#xA;Log in to the web interface as an admin&#xA;Navigate to Administration   Authentication   LDAP Settings&#xA;&#xA;Here&#39;s a picture, see below for details:&#xA;picture of the below settings in the Zabbix web configuration area&#xA;&#xA;Enable LDAP authentication&#xA;&#xA;Checked&#xA;&#xA;LDAP host&#xA;&#xA;URI of your LLDAP host. Example: ldap://ldap.example.com:3890 or ldaps://ldap.example.com:6360 for TLS.&#xA;&#xA;Port&#xA;&#xA;Not used when using a full LDAP URI as above, but feel free to put 3890 or 6360 for TLS.&#xA;&#xA;Base DN&#xA;&#xA;Your LLDAPLDAPBASE. Example: dc=example,dc=com&#xA;&#xA;Search attribute&#xA;&#xA;uid&#xA;&#xA;Case-sensitive login&#xA;&#xA;Checked&#xA;&#xA;Bind DN&#xA;&#xA;uid=admin,ou=people,dc=example,dc=com&#xA;&#xA;Alternately, it is recommended that you create a separate user account (e.g, binduser) instead of admin for sharing Bind credentials with other services. The binduser should be a member of the lldapstrict_readonly group to limit access to your LDAP configuration in LLDAP.&#xA;&#xA;Bind password&#xA;&#xA;Password for the above bind DN user.&#xA;&#xA;Test authentication&#xA;&#xA;The test authentication Login and User password must be used to check the connection and whether an LDAP user can be successfully authenticated. Zabbix will not activate LDAP authentication if it is unable to authenticate the test user.&#xA;&#xA;Enable LDAP in Zabbix Web&#xA;&#xA;Navigate to Administration   Authentication   Authentication (the first tab)&#xA;Set &#34;Default authentication&#34; to &#34;LDAP&#34;&#xA;Click &#34;Update&#34;&#xA;&#xA;---&#xA;Filed in: #solutions]]&gt;</description>
      <content:encoded><![CDATA[<p>I wrote a <a href="https://github.com/lldap/lldap/blob/main/example_configs/zabbix-web.md">document</a> for configuring <a href="https://www.zabbix.com/">Zabbix</a> 6.0 web interface to use <a href="https://github.com/lldap/lldap">LLDAP</a> for logins. Here is the same information, with pictures.</p>



<p>This example is for the Zabbix Web interface <strong>version 6.0</strong>, which is the supported LTS version as of August 2023.  Later versions have additional options.</p>

<p>For the associated 6.0 documentation see <a href="https://www.zabbix.com/documentation/6.0/en/manual/web_interface/frontend_sections/administration/authentication">here</a> and for the current manual see <a href="https://www.zabbix.com/documentation/current/en/manual">here</a>.</p>

<p><strong><em>Note that an LDAP user must exist in Zabbix Web as well, however its Zabbix password will not be used.</em></strong> When creating the user in Zabbix, the user should also be added to your desired Zabbix roles/groups.</p>

<h2 id="configure-ldap-settings">Configure LDAP Settings</h2>
<ul><li>Log in to the web interface as an admin</li>
<li>Navigate to <code>Administration &gt; Authentication &gt; LDAP Settings</code></li></ul>

<p>Here&#39;s a picture, see below for details:
<img src="https://dabor.kiserai.net/i/cee7e227-16c2-4a0f-86e8-5bf2adcc4184.jpg" alt="picture of the below settings in the Zabbix web configuration area"></p>

<h3 id="enable-ldap-authentication">Enable LDAP authentication</h3>

<p>Checked</p>

<h3 id="ldap-host">LDAP host</h3>

<p>URI of your LLDAP host. Example: <code>ldap://ldap.example.com:3890</code> or <code>ldaps://ldap.example.com:6360</code> for TLS.</p>

<h3 id="port">Port</h3>

<p>Not used when using a full LDAP URI as above, but feel free to put <code>3890</code> or <code>6360</code> for TLS.</p>

<h3 id="base-dn">Base DN</h3>

<p>Your LLDAP<em>LDAP</em>BASE. Example: <code>dc=example,dc=com</code></p>

<h3 id="search-attribute">Search attribute</h3>

<p><code>uid</code></p>

<h3 id="case-sensitive-login">Case-sensitive login</h3>

<p>Checked</p>

<h3 id="bind-dn">Bind DN</h3>

<p><code>uid=admin,ou=people,dc=example,dc=com</code></p>

<p>Alternately, it is recommended that you create a separate user account (e.g, <code>bind_user</code>) instead of <code>admin</code> for sharing Bind credentials with other services. The <code>bind_user</code> should be a member of the <code>lldap_strict_readonly</code> group to limit access to your LDAP configuration in LLDAP.</p>

<h3 id="bind-password">Bind password</h3>

<p>Password for the above bind DN user.</p>

<h3 id="test-authentication">Test authentication</h3>

<p>The test authentication <code>Login</code> and <code>User password</code> must be used to check the connection and whether an LDAP user can be successfully authenticated. Zabbix will not activate LDAP authentication if it is unable to authenticate the test user.</p>

<h2 id="enable-ldap-in-zabbix-web">Enable LDAP in Zabbix Web</h2>
<ul><li>Navigate to <code>Administration &gt; Authentication &gt; Authentication</code> (the first tab)</li>
<li>Set “Default authentication” to “LDAP”</li>
<li>Click “Update”</li></ul>

<hr>

<p>Filed in: <a href="https://blog.kiserai.net/tag:solutions" class="hashtag"><span>#</span><span class="p-category">solutions</span></a></p>
]]></content:encoded>
      <guid>https://blog.kiserai.net/zabbix-web-interface-with-lldap</guid>
      <pubDate>Tue, 08 Aug 2023 20:20:53 +0000</pubDate>
    </item>
    <item>
      <title>Stellaris Custom Empire: Prime Collective (from Peter F. Hamilton&#39;s Commonwealth saga)</title>
      <link>https://blog.kiserai.net/stellaris-custom-empire-prime-collective-from-peter-f</link>
      <description>&lt;![CDATA[Requirements&#xA;&#xA;Cybrxkhan&#39;s Assortment of Namelists for Stellaris&#xA;&#xA;DESCRIPTION&#xA;&#xA;The Primes are a xenophobic, aggressively expansionist alien species originating in the Dyson Alpha system. ... The race is extremely xenophobic, to the point that individual immotiles view the very existence of other independent life forms as a threat to their continued existence. ... This xenophobia is so extreme that the Prime exterminated all mobile life on their home world, lest it ever become a threat, and upon gaining nuclear technology immediately and unhesitatingly used it against each other, stopping only when the damage to their world became so extreme that it threatened the survival of the remaining immotiles. Upon contact with humans, the immotile collective known as MorningLightMountain immediately deployed wormhole technology to eliminate every other immotile, leaving it and its offspring as the only representative of its race on the homeworld. It then proceeded to immediately turn all its forces against humanity, as the very possibility of not destroying them was beyond its comprehension. &#xA;!--more--&#xA;Picture&#xA;&#xA;A picture of the in-game empire summary screen&#xA;&#xA;Code (3.8.4)&#xA;&#xA;&#34;Prime Collective&#34;={&#xA;        key=&#34;Prime Collective&#34;&#xA;        shipprefix={&#xA;                key=&#34;ISS&#34;&#xA;        }&#xA;        species={&#xA;                class=&#34;LITHOID&#34;&#xA;                portrait=&#34;lith8&#34;&#xA;                speciesname={&#xA;                        key=&#34;Prime&#34;&#xA;                        literal=yes&#xA;                }&#xA;                speciesplural={&#xA;                        key=&#34;Primes&#34;&#xA;                        literal=yes&#xA;                }&#xA;                speciesadjective={&#xA;                        key=&#34;Prime&#34;&#xA;                        literal=yes&#xA;                }&#xA;                speciesbio=&#34;The Primes are a xenophobic, aggressively expansionist alien species originating in the Dyson Alpha system. ... The race is extremely xenophobic, to the point that individual immotiles view the very existence of other independent life forms as a threat to their continued existence. ... This xenophobia is so extreme that the Prime exterminated all mobile life on their home world, lest it ever become a threat, and upon gaining nuclear technology immediately and unhesitatingly used it against each other, stopping only when the damage to their world became so extreme that it threatened the survival of the remaining immotiles.&#34;&#xA;                namelist=&#34;cybrxkhanabstract3&#34;&#xA;                gender=indeterminable&#xA;                trait=&#34;traitlithoid&#34;&#xA;                trait=&#34;traithivemind&#34;&#xA;                trait=&#34;traitsurvivor&#34;&#xA;                trait=&#34;traitindustrious&#34;&#xA;                trait=&#34;traitnaturalphysicists&#34;&#xA;                trait=&#34;traitstrong&#34;&#xA;                trait=&#34;traitrepugnant&#34;&#xA;        }&#xA;        name={&#xA;                key=&#34;Prime Collective&#34;&#xA;                literal=yes&#xA;        }&#xA;        adjective={&#xA;                key=&#34;%ADJ%&#34;&#xA;                variables={&#xA;                        {&#xA;                                key=&#34;adjective&#34;&#xA;                                value={&#xA;                                        key=&#34;Primes&#34;&#xA;                                        literal=yes&#xA;                                }&#xA;                        }&#xA;&#xA;                }&#xA;        }&#xA;        authority=&#34;authhivemind&#34;&#xA;        government=&#34;govdevouringswarm&#34;&#xA;        planetname={&#xA;                key=&#34;Dyson Alpha Arche&#34;&#xA;                literal=yes&#xA;        }&#xA;        planetclass=&#34;pctropical&#34;&#xA;        systemname={&#xA;                key=&#34;Dyson Pair&#34;&#xA;                literal=yes&#xA;        }&#xA;        initializer=&#34;customstartinginit03&#34;&#xA;        graphicalculture=&#34;arthropoid01&#34;&#xA;        citygraphicalculture=&#34;arthropoid01&#34;&#xA;        empireflag={&#xA;                icon={&#xA;                        category=&#34;lithoid&#34;&#xA;                        file=&#34;lithoid12.dds&#34;&#xA;                }&#xA;                background={&#xA;                        category=&#34;backgrounds&#34;&#xA;                        file=&#34;invertedv.dds&#34;&#xA;                }&#xA;                colors={&#xA;                        &#34;redorange&#34;&#xA;                        &#34;yellow&#34;&#xA;                        &#34;black&#34;&#xA;                        &#34;null&#34;&#xA;                }&#xA;        }&#xA;        ruler={&#xA;                gender=indeterminable&#xA;                name={&#xA;                        fullnames={&#xA;                                key=&#34;MorningLightMountain&#34;&#xA;                                literal=yes&#xA;                        }&#xA;                }&#xA;                portrait=&#34;lith8&#34;&#xA;                texture=1&#xA;                attachment=0&#xA;                clothes=0&#xA;                rulertitle={&#xA;                        key=&#34;Immotile&#34;&#xA;                        literal=yes&#xA;                }&#xA;                trait=&#34;traitrulerwarlike&#34;&#xA;                leaderclass=&#34;general&#34;&#xA;        }&#xA;        spawnasfallen=no&#xA;        ignoreportraitduplication=no&#xA;        room=&#34;lithoidroom&#34;&#xA;        spawnenabled=always&#xA;        ethic=&#34;ethicgestaltconsciousness&#34;&#xA;        civics={&#xA;                &#34;civichivedevouringswarm&#34;&#xA;                &#34;civichivenaturalneuralnetwork&#34;&#xA;        }&#xA;        origin=&#34;originpost_apocalyptic&#34;&#xA;}&#xA;---&#xA;Filed in: #stellaris]]&gt;</description>
      <content:encoded><![CDATA[<h2 id="requirements">Requirements</h2>

<p><a href="https://steamcommunity.com/sharedfiles/filedetails/?id=682691478">Cybrxkhan&#39;s Assortment of Namelists for Stellaris</a></p>

<h2 id="description">DESCRIPTION</h2>

<p>The Primes are a xenophobic, aggressively expansionist alien species originating in the Dyson Alpha system. ... The race is extremely xenophobic, to the point that individual immotiles view the very existence of other independent life forms as a threat to their continued existence. ... This xenophobia is so extreme that the Prime exterminated all mobile life on their home world, lest it ever become a threat, and upon gaining nuclear technology immediately and unhesitatingly used it against each other, stopping only when the damage to their world became so extreme that it threatened the survival of the remaining immotiles. Upon contact with humans, the immotile collective known as MorningLightMountain immediately deployed wormhole technology to eliminate every other immotile, leaving it and its offspring as the only representative of its race on the homeworld. It then proceeded to immediately turn all its forces against humanity, as the very possibility of not destroying them was beyond its comprehension.
</p>

<h2 id="picture">Picture</h2>

<p><img src="https://dabor.kiserai.net/i/13c36cba-6549-4bbd-87d5-dce31688ca11.jpg" alt="A picture of the in-game empire summary screen"></p>

<h2 id="code-3-8-4">Code (3.8.4)</h2>

<pre><code class="language-sh">&#34;Prime Collective&#34;={
        key=&#34;Prime Collective&#34;
        ship_prefix={
                key=&#34;ISS&#34;
        }
        species={
                class=&#34;LITHOID&#34;
                portrait=&#34;lith8&#34;
                species_name={
                        key=&#34;Prime&#34;
                        literal=yes
                }
                species_plural={
                        key=&#34;Primes&#34;
                        literal=yes
                }
                species_adjective={
                        key=&#34;Prime&#34;
                        literal=yes
                }
                species_bio=&#34;The Primes are a xenophobic, aggressively expansionist alien species originating in the Dyson Alpha system. ... The race is extremely xenophobic, to the point that individual immotiles view the very existence of other independent life forms as a threat to their continued existence. ... This xenophobia is so extreme that the Prime exterminated all mobile life on their home world, lest it ever become a threat, and upon gaining nuclear technology immediately and unhesitatingly used it against each other, stopping only when the damage to their world became so extreme that it threatened the survival of the remaining immotiles.&#34;
                name_list=&#34;cybrxkhan_abstract_3&#34;
                gender=indeterminable
                trait=&#34;trait_lithoid&#34;
                trait=&#34;trait_hive_mind&#34;
                trait=&#34;trait_survivor&#34;
                trait=&#34;trait_industrious&#34;
                trait=&#34;trait_natural_physicists&#34;
                trait=&#34;trait_strong&#34;
                trait=&#34;trait_repugnant&#34;
        }
        name={
                key=&#34;Prime Collective&#34;
                literal=yes
        }
        adjective={
                key=&#34;%ADJ%&#34;
                variables={
                        {
                                key=&#34;adjective&#34;
                                value={
                                        key=&#34;Primes&#34;
                                        literal=yes
                                }
                        }

                }
        }
        authority=&#34;auth_hive_mind&#34;
        government=&#34;gov_devouring_swarm&#34;
        planet_name={
                key=&#34;Dyson Alpha Arche&#34;
                literal=yes
        }
        planet_class=&#34;pc_tropical&#34;
        system_name={
                key=&#34;Dyson Pair&#34;
                literal=yes
        }
        initializer=&#34;custom_starting_init_03&#34;
        graphical_culture=&#34;arthropoid_01&#34;
        city_graphical_culture=&#34;arthropoid_01&#34;
        empire_flag={
                icon={
                        category=&#34;lithoid&#34;
                        file=&#34;lithoid_12.dds&#34;
                }
                background={
                        category=&#34;backgrounds&#34;
                        file=&#34;inverted_v.dds&#34;
                }
                colors={
                        &#34;red_orange&#34;
                        &#34;yellow&#34;
                        &#34;black&#34;
                        &#34;null&#34;
                }
        }
        ruler={
                gender=indeterminable
                name={
                        full_names={
                                key=&#34;MorningLightMountain&#34;
                                literal=yes
                        }
                }
                portrait=&#34;lith8&#34;
                texture=1
                attachment=0
                clothes=0
                ruler_title={
                        key=&#34;Immotile&#34;
                        literal=yes
                }
                trait=&#34;trait_ruler_warlike&#34;
                leader_class=&#34;general&#34;
        }
        spawn_as_fallen=no
        ignore_portrait_duplication=no
        room=&#34;lithoid_room&#34;
        spawn_enabled=always
        ethic=&#34;ethic_gestalt_consciousness&#34;
        civics={
                &#34;civic_hive_devouring_swarm&#34;
                &#34;civic_hive_natural_neural_network&#34;
        }
        origin=&#34;origin_post_apocalyptic&#34;
}
</code></pre>

<hr>

<p>Filed in: <a href="https://blog.kiserai.net/tag:stellaris" class="hashtag"><span>#</span><span class="p-category">stellaris</span></a></p>
]]></content:encoded>
      <guid>https://blog.kiserai.net/stellaris-custom-empire-prime-collective-from-peter-f</guid>
      <pubDate>Wed, 28 Jun 2023 22:44:56 +0000</pubDate>
    </item>
    <item>
      <title>Elite: Dangerous Utilities</title>
      <link>https://blog.kiserai.net/elite-dangerous-utilities</link>
      <description>&lt;![CDATA[Sirius Corporation Covert Creations (SCCC)&#xA;&#xA;Not affiliated with Li-Yong Rui, PowerPlay, nor any player minor factions. Still secretly controlling a galaxy near you.&#xA;&#xA;Bounty Hunting Spot Finder&#xA;&#xA;Find RES/CNB  near you, dynamically updated as the galaxy changes.&#xA;&#xA;https://siriuscorp.cc/bounty/&#xA;&#xA;Ship Anatomy (Rehost)&#xA;&#xA;Rehost of Anton Natarov&#39;s interactive ship anatomy tool.&#xA;&#xA;https://siriuscorp.cc/edsa/&#xA;!--more--&#xA;Guides&#xA;&#xA;Various guides on mining, Robigo, etc.&#xA;&#xA;https://siriuscorp.cc/guides/&#xA;&#xA;Community Goal Progress Graphs&#xA;&#xA;https://siriuscorp.cc/goal/&#xA;&#xA;Graph&#xA;&#xA;Space Conflict Zone / War Finder&#xA;&#xA;https://siriuscorp.cc/conflict/&#xA;&#xA;---&#xA;Filed in: #elitedangerous]]&gt;</description>
      <content:encoded><![CDATA[<p><a href="https://siriuscorp.cc/">Sirius Corporation Covert Creations (SCCC)</a></p>

<p>Not affiliated with Li-Yong Rui, PowerPlay, nor any player minor factions. Still secretly controlling a galaxy near you.</p>

<h2 id="bounty-hunting-spot-finder">Bounty Hunting Spot Finder</h2>

<p>Find RES/CNB  near you, dynamically updated as the galaxy changes.</p>

<p><a href="https://siriuscorp.cc/bounty/">https://siriuscorp.cc/bounty/</a></p>

<h2 id="ship-anatomy-rehost">Ship Anatomy (Rehost)</h2>

<p>Rehost of Anton Natarov&#39;s interactive ship anatomy tool.</p>

<p><a href="https://siriuscorp.cc/edsa/">https://siriuscorp.cc/edsa/</a>
</p>

<h2 id="guides">Guides</h2>

<p>Various guides on mining, Robigo, etc.</p>

<p><a href="https://siriuscorp.cc/guides/">https://siriuscorp.cc/guides/</a></p>

<h2 id="community-goal-progress-graphs">Community Goal Progress Graphs</h2>

<p><a href="https://siriuscorp.cc/goal/">https://siriuscorp.cc/goal/</a></p>

<p><img src="https://siriuscorp.cc/goal/776-775-perhr.webp" alt="Graph"></p>

<h2 id="space-conflict-zone-war-finder">Space Conflict Zone / War Finder</h2>

<p><a href="https://siriuscorp.cc/conflict/">https://siriuscorp.cc/conflict/</a></p>

<hr>

<p>Filed in: <a href="https://blog.kiserai.net/tag:elitedangerous" class="hashtag"><span>#</span><span class="p-category">elitedangerous</span></a></p>
]]></content:encoded>
      <guid>https://blog.kiserai.net/elite-dangerous-utilities</guid>
      <pubDate>Wed, 28 Jun 2023 22:21:04 +0000</pubDate>
    </item>
  </channel>
</rss>