<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
    <channel>
      <title>Simon Dalvai</title>
      <link>https://simondalvai.org</link>
      <description></description>
      <generator>Zola</generator>
      <language>en</language>
      <atom:link href="https://simondalvai.org/rss.xml" rel="self" type="application/rss+xml"/>
      <lastBuildDate>Fri, 26 Jun 2026 10:20:00 +0000</lastBuildDate>
      <item>
          <title>My main Android phone is now 99% Google free</title>
          <pubDate>Fri, 26 Jun 2026 10:20:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/google-free-android/</link>
          <guid>https://simondalvai.org/blog/google-free-android/</guid>
          <description xml:base="https://simondalvai.org/blog/google-free-android/">&lt;p&gt;As of today, I run my phone Google free (at least everywhere I can influence).&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;With pure LineageOS 23.2&lt;&#x2F;li&gt;
&lt;li&gt;No Google account&lt;&#x2F;li&gt;
&lt;li&gt;No Google Play Store or compatible clients like AuroraStore&lt;&#x2F;li&gt;
&lt;li&gt;No Google Play Services&lt;&#x2F;li&gt;
&lt;li&gt;No Google Apps at all, also no Google Maps&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;On the surface it is indeed 100% Google free.
But Android is made by Google, therefore some internal services might still phone home.
For example I know that GrapheneOS has an option to use their servers for connectivity pings.
So I guess some system apps still use Google servers, even when using LineageOS.
Therefore the title says 99% and not 100%.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-no-google&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-no-google&quot; aria-label=&quot;Anchor link for: why-no-google&quot;&gt;Why no Google&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I have many reasons why I don&#x27;t want any Google or other big tech software on my phone.
Mainly due to pricacy reasons, but not only.
I guess everybody has to do their research and decide, what software to trust.&lt;&#x2F;p&gt;
&lt;p&gt;I can only say that it was a very liberating feeling, and still is today.
Knowing that I own my device and that (nearly) no one can track me makes me feel free and safe.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-daily-driver&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-daily-driver&quot; aria-label=&quot;Anchor link for: my-daily-driver&quot;&gt;My daily driver&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Three years ago I bought a used Google Pixel 5, because I wanted to try GrapheneOS.
I chose this phone, because it was (and still is) on of the smallest Pixel phones.
I really don&#x27;t like the big bricks most modern smart phones have become.
Is still works perfectly and I replaced the battery after one year.
I didn&#x27;t expect that already three years passed, when searching for my order confirmation email.
This confirms that with some dedication, even used Android phones can last for years&lt;&#x2F;p&gt;
&lt;h2 id=&quot;second-android-phone&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#second-android-phone&quot; aria-label=&quot;Anchor link for: second-android-phone&quot;&gt;Second Android phone&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Before explaining my setup in more detail, I want to clarify, that I still use a second phone.
It is an older stock Android phone, with all Google stuff on it.
I need still need to use banking and other apps, that don&#x27;t work on custom roms.&lt;&#x2F;p&gt;
&lt;p&gt;But this has also another big advantage: I can leave my important apps &quot;at home&quot;.
This second phone never leaves my house and therefore I can&#x27;t loose it.
It also allows me to do whatever I want with my main phone.
Flashing new roms, experimenting new features or whatever would need a full wipe of my phone.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;grapheneos&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#grapheneos&quot; aria-label=&quot;Anchor link for: grapheneos&quot;&gt;GrapheneOS&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Good that I wrote about &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;install-lineageos-pixel5&#x2F;&quot;&gt;flashing LineageOS&lt;&#x2F;a&gt;
in 2023.
Otherwise I won&#x27;t have remembered, that I did not install GrapheneOS immediately.&lt;&#x2F;p&gt;
&lt;p&gt;Note: the last GrapheneOS version on my Pixel 5 was
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;grapheneos.org&#x2F;releases#2024101200&quot;&gt;2024101200&lt;&#x2F;a&gt;.
Therefore the following text is related to that version and new versions features could differ.&lt;&#x2F;p&gt;
&lt;p&gt;For over a year I used GrapheneOS on my Pixel 5.
It works really well, because of their Sandboxed Google Play Services.
This allows that notifications arrive on time and that Google Maps works.
This way the original Play Services run in a sandbox, where you decide it&#x27;s permissions.
Normally this services have nearly root access on your device.&lt;&#x2F;p&gt;
&lt;p&gt;Features I miss from GrapheneOS today, are the automated Bluetooth&#x2F;WiFi turnoff.
When disconnected for over 5 minutes, both turn off, to safe battery and reduce the attack surface.
I mostly care about the battery life.&lt;&#x2F;p&gt;
&lt;p&gt;Another cool security feature is that the phone can be locked, by using the wrong finger to unlock.
When tapped 5 times, the fingerprint sensor is disabled, and the password is needed to unlock.
I luckily never needed this feature and hope I will never have to.
But this shows how dedicated the GrapheneOS team is regarding security hardening.&lt;&#x2F;p&gt;
&lt;p&gt;I also used contact scopes, that allow to limit what contacts and app can see.
Just like it is possible with pictures in the gallery, but for contacts.
This way I could limit Whatsapp to access only the few contacts I needed.&lt;&#x2F;p&gt;
&lt;p&gt;Then one day I got the notification that my phone is no longer supported.
I continued using it anyways for some time, because I really liked it.
Buying a newer supported Pixel was no option, due to the size they have.
And my Pixel 5 still works perfectly fine.
For this reasons I switched back to LinageOS.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lineageos-without-google-play-services&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#lineageos-without-google-play-services&quot; aria-label=&quot;Anchor link for: lineageos-without-google-play-services&quot;&gt;LineageOS without Google Play Services&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I really like the LineageOS project, because it is the successor of CynaogenMod.
That brings good memories back, from my first days messing around with custom roms.
Once I even hard bricked my phone, because I installed a rom from another phone.
I learned it the hard way, that phone and version numbers must match :-)&lt;&#x2F;p&gt;
&lt;p&gt;First I wanted to replicate the experience I had with GrapheneOS and the Google Play Services.
So I tried microG for some days, but I never got it working correctly.
I can&#x27;t remember exactly what went wrong, but I did not like the constant tweaking.&lt;&#x2F;p&gt;
&lt;p&gt;So I decided to try without any Play Services at all.
For that I had to remove microG, and reinstall Whatsapp and Signal.
When this apps are opened for the first time, they check if the Play Services exist.
If not, they start using Websockets to get notifications, afaik.
I have to say that Signal works perfectly and I get notifications instantly.
Whatsapp notifications on the other hand sometimes take over 20 minutes to arrive.
I suspect that Signal simply has more users and reasons to support websockets better.
But in the end I don&#x27;t mind about this delay.
Anyways I want to use my phone less, so this delay helps to achieve that perfectly.&lt;&#x2F;p&gt;
&lt;p&gt;Note: Notifications work best, when allowing background usage in app battery settings.
The delays only happen, once the phone enters in &quot;sleep mode&quot;, after some minutes of not using it.
While actively using the phone, all notifications arrive on time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;apps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#apps&quot; aria-label=&quot;Anchor link for: apps&quot;&gt;Apps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now I have a very minimalist phone, with just a few apps.
The battery life is very good with at least 2 days of use, because I don&#x27;t use my phone much now.
Everything while keeping the charge between 20% and 80%, to reduce battery cycles and consumption.&lt;&#x2F;p&gt;
&lt;p&gt;Since many years I use Unlauncher as may home launcher.
It allows only up to 6 apps on the home screen and is text only.
The black background with the few text saves also quite some battery with OLED screens.&lt;&#x2F;p&gt;
&lt;p&gt;To get my apps I use F-Droid and the following apps are all from there.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Unlauncher - Text only home app&lt;&#x2F;li&gt;
&lt;li&gt;Fennec - Firefox fork&lt;&#x2F;li&gt;
&lt;li&gt;K9Mail&lt;&#x2F;li&gt;
&lt;li&gt;Markor - Text editor for notes&lt;&#x2F;li&gt;
&lt;li&gt;KeepassXD - For passwords&lt;&#x2F;li&gt;
&lt;li&gt;Aegis - 2FA that allows backups&lt;&#x2F;li&gt;
&lt;li&gt;Termux - Linux terminal
&lt;ul&gt;
&lt;li&gt;For synchting&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Fitotrack - Local sports tracking&lt;&#x2F;li&gt;
&lt;li&gt;CoMaps - Offline maps&lt;&#x2F;li&gt;
&lt;li&gt;SicMu Player - Music&lt;&#x2F;li&gt;
&lt;li&gt;AntennaPod - Podcasts&lt;&#x2F;li&gt;
&lt;li&gt;Lichess - Because I like chess :-)&lt;&#x2F;li&gt;
&lt;li&gt;DAVx5&lt;&#x2F;li&gt;
&lt;li&gt;Signal&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;To get Signal into F-Droid, I added The Guardian Project repository.
But I just saw that Signal can now auto-update itself, by downloading new versions on it&#x27;s own.
So technically now the apk needs to be downloaded only once from the official website.&lt;&#x2F;p&gt;
&lt;p&gt;The only two proprietary apps I currently use are Whatsapp and Steam.
I need the Steam app for 2FA and build confirmation, when releasing updates for my games.
Both have their apk hosted on their official websites.
I used to get them from the Aurora Store, a FOSS Google Play Store client.
But now I simply check periodically, if a new version is online.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;maps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#maps&quot; aria-label=&quot;Anchor link for: maps&quot;&gt;Maps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;On of the biggest issues most have without Google Play Services is that Google Maps doesn&#x27;t work.
Many use it for navigation and to get real time traffic information.
Luckily I don&#x27;t have car, so I don&#x27;t need real time traffic information.&lt;&#x2F;p&gt;
&lt;p&gt;Currently I use CoMaps and it works very well.
It works offline and is based on OpenStreetMap data and maps.
This way (at least in Europe) I get often even more information than with Google Maps.
Especially for hiking trails in the mountains and drinking water locations.&lt;&#x2F;p&gt;
&lt;p&gt;For some more complex and long distance bike routing, I also use OSMAnd+ and brouter.de.
But only when I make long distance bike tours.&lt;&#x2F;p&gt;
&lt;p&gt;The only thing I sometimes miss from Google Maps are restaurant reviews and updated opening hours.
In this rare cases, I simply open Google Maps in my browser using the desktop mode.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;about-the-cloud&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#about-the-cloud&quot; aria-label=&quot;Anchor link for: about-the-cloud&quot;&gt;About the cloud&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&quot;There is no cloud, just other peoples computers&quot;, has a really good point.
With my setup, the are no other peoples computers, but my Rasperry Pi running at home 24&#x2F;7.
I no longer use any other cloud solution to host my data.
A big wakeup call was to see how difficult it was, to remove all my data from Google Drive.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;contacts-and-calendar&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#contacts-and-calendar&quot; aria-label=&quot;Anchor link for: contacts-and-calendar&quot;&gt;Contacts and Calendar&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Without Google apps, I need so save and synchronize my contacts and calendars in another way.
Currently I use mailbox.org as my mail provider and that can host that for me.
On my phone I use DAVx5 to synchronize everything.
This way I can access my contacts and calendar also from other devices.&lt;&#x2F;p&gt;
&lt;p&gt;The next step would be to self-host this, but for now I trust mailbox.org.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;passwords&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#passwords&quot; aria-label=&quot;Anchor link for: passwords&quot;&gt;Passwords&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;For passwords and other sensible data, I use KeePass since many years.
It is very safe and very local, if you keep it local and don&#x27;t store it &lt;em&gt;somewhere&lt;&#x2F;em&gt; online.&lt;&#x2F;p&gt;
&lt;p&gt;A KeePass file can also easily be used and shared between devices.
On my phone I use KeepassXD and on my linux computers KeepassXC.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;syncthing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#syncthing&quot; aria-label=&quot;Anchor link for: syncthing&quot;&gt;Syncthing&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Syncthing allows to share directories and it&#x27;s files between devices, like my Keepass file.
So I have one single sync directory, that contains everything I need across devices.
It uses peer to peer connections and does not need any cloud service.
For this reason I have a always on Rasperry Pi at home.
This way I can sync everything, even when outside my home network and with my main computer off.&lt;&#x2F;p&gt;
&lt;p&gt;I won&#x27;t go too much into detail here, because this would paragraph would explode very fast.
But I can say that this works very well, especially if the amount of files is kept to a few MB.
For bigger files and backups, I simply use cables good old hard disk backups.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;linux-phone-i-m-coming&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#linux-phone-i-m-coming&quot; aria-label=&quot;Anchor link for: linux-phone-i-m-coming&quot;&gt;Linux phone I&#x27;m coming!&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I really think if my Pixel 5 breaks one day or Android closes it&#x27;s door, I will try a Linux phone.
The postmarketOS project is very promising and already has some supported devices.
Maybe even my Pixel 5 will be supported one day.&lt;&#x2F;p&gt;
&lt;p&gt;I suspect my main messaging apps Signal and Whatsapp might not work very well yet.
I just read that Signal Desktop or Whatsapp Web can be used.
But I don&#x27;t think that notifications will work, and if they do, it surely drains the battery.&lt;&#x2F;p&gt;
&lt;p&gt;I hope one day there will be a Linux phone with good battery life and reliable basic features.
I can life without Whatsapp or Signal on me 24&#x2F;7.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Translating my Godot game with Weblate</title>
          <pubDate>Wed, 20 May 2026 20:07:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-weblate-translation/</link>
          <guid>https://simondalvai.org/blog/godot-weblate-translation/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-weblate-translation/">&lt;p&gt;My Godot game &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;99managers.org&quot;&gt;99Managers&lt;&#x2F;a&gt;,
a sport management game, has a lot of UI and text.
All buttons, labels and emails can be translated to reach more players.
Godot supports simple csv or the more feature rich gettext for translations.&lt;br &#x2F;&gt;
Translation platforms like Weblate instead, allow to translate a game without ever opening Godot.
No developer skills needed and everything can be done on a nice and user-friendly website.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;weblate&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#weblate&quot; aria-label=&quot;Anchor link for: weblate&quot;&gt;Weblate&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;weblate.org&quot;&gt;Weblate&lt;&#x2F;a&gt;
is a FOSS translation platform, that generously gives free hosting for open source projects.
I&#x27;ve been using it now for about a year and I have to say: Thank you Weblate!
In that time my game has been translated to over 12 languages by 45 contributors.
Therefore also a big Thank you to all contributors!
You can see the current translation status on my projects
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;hosted.weblate.org&#x2F;projects&#x2F;99-managers-futsal-edition&#x2F;&quot;&gt;Weblate page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Weblate has a big community of translators.
Therefore you might get translations from people that simply like translating FOSS projects.
This way also non-developers can contribute and help the FOSS ecosystem.&lt;&#x2F;p&gt;
&lt;p&gt;Connecting a game to Weblate takes time, but normally once setup, no further intervention is needed.
I won&#x27;t go into detail on this, since the setup might differ from project to project.
The best place to get started is the official &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.weblate.org&#x2F;&quot;&gt;Weblate docs&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Note: Weblate can also be used for closed source projects by paying or trough self-hosting.
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;translate.codeberg.org&quot;&gt;Codeberg&lt;&#x2F;a&gt; also hosts a Weblate server for the projects hosted
there.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;csv-vs-gettext&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#csv-vs-gettext&quot; aria-label=&quot;Anchor link for: csv-vs-gettext&quot;&gt;csv vs gettext&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As in all my previous games, I used the simple key&#x2F;value csv file for translations.
Weblate accepts a lot of file formats for translations and supports also those csv files.
But things got ugly very fast.
I can&#x27;t remember what problems I faced, but I quickly migrated to
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;i18n&#x2F;localization_using_gettext.html&quot;&gt;gettext&lt;&#x2F;a&gt;.
Gettext is afaik the best supported format on Weblate and other translation platforms.&lt;&#x2F;p&gt;
&lt;p&gt;The first big difference between csv and gettext, is that gettext uses the original string as id.
So for example the csv key &quot;ABOUT_TEXT&quot; simply becomes &quot;This game is a FOSS Futal management game&quot;.
This has the big advantage that you already can see the real text in the Godot editor.
This also means that the if the base string changes, all translations need to be updated.
But gettext is quite smart and keeps the old outdated translation, so nothing is lost.&lt;&#x2F;p&gt;
&lt;p&gt;Another big advantage of using gettext is translation context.
For example some words might mean different things depending on the context.
The word &quot;Menu&quot; can have different meanings if used on a button or as label on in a Restaurant.
By providing the context gettext, adds the context information to the template file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;button.text = tr(&amp;quot;Menu&amp;quot;, &amp;quot;Button&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;restaurant_menu_label.text = tr(&amp;quot;Menu&amp;quot;, &amp;quot;Restaurant&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This make is possible to have two different translations for the same word.
It also helps the translator to understand in which context the word is used.&lt;&#x2F;p&gt;
&lt;p&gt;You can even add more information with the &quot;# TRANSLATORS:&quot; comment.
I mostly use it to show an example for strings with placeholders.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# TRANSLATORS: Example: The Italian Cup has been won by Bolzano.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;cup_info.text = &amp;quot;The {competition_name} has been won by {team_name}.&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;pot-po-files&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#pot-po-files&quot; aria-label=&quot;Anchor link for: pot-po-files&quot;&gt;pot&#x2F;po files&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Gettext uses pot&#x2F;po files, that get generated automatically from the source code.
The base language is located in the pot file, also called template.
All translations instead are done in po files.&lt;&#x2F;p&gt;
&lt;p&gt;Technically a this files can also be crafted by hand, because they are pure text and very simple.
The keyword msgid points to the original string and msgtstr the translation.
In the template, msgtstr stays empty.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; template.pot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;msgid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Hello World!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;msgstr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;msgid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;This is a pot file.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;msgstr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And here the Italian translation po file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; it_IT.po&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;msgid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Hello World!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;msgstr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Ciao Mondo!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;msgid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;This is a pot file.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;msgstr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;Questo è un file pot.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;generation-pot-files-with-the-godot-editor&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#generation-pot-files-with-the-godot-editor&quot; aria-label=&quot;Anchor link for: generation-pot-files-with-the-godot-editor&quot;&gt;Generation pot files with the Godot Editor&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Godot assumes that every Node that has text should be translated.
To prevent that a Node gets translated, you can set Auto Translate to Disabled in the inspector.
For GDScript instead, it follows some
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;latest&#x2F;tutorials&#x2F;i18n&#x2F;localization_using_gettext.html#extracting-localizable-strings-from-gdscript-files&quot;&gt;simple rules&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Godot then generates the .pot file automatically for you.
But it needs to know which scenes or scripts contain translations.
This can be set in Project &amp;gt; Project Settings &amp;gt; Localization &amp;gt; Template Generation.
There is no &quot;translate everything&quot; checkbox yet.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;template-generation.webp&quot; alt=&quot;Screenshot of Godot pot file generation screen&quot;&gt;  
&lt;p&gt;After clicking the Generate button, the pot template file is generated.
The pot template can be used to create po translation files.
Weblate for example just needs the pot file and creates the po files automatically.&lt;&#x2F;p&gt;
&lt;p&gt;Once you have a po file, it can be added in Project &amp;gt; Project Settings &amp;gt; Localization &amp;gt; Translations.
This makes the language available to the TranslationServer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;print(tr(&amp;quot;Hello World!&amp;quot;)) # Hello World!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var locale: String = &amp;quot;it_IT&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;TranslationServer.set_locale(locale)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;print(tr(&amp;quot;Hello World!&amp;quot;)) # Ciao Mondo!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &quot;Files with translations strings&quot; list from the last image can become a nightmare to maintain.
New or renamed files need to be added manually every time.
I often forgot this, leading to missing translations.&lt;&#x2F;p&gt;
&lt;p&gt;There are some interesting addons I saw that would make this much easier.
For example &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;airotto&#x2F;Godot-POT-Plugin&quot;&gt;Godot-POT-Plugin&lt;&#x2F;a&gt;
shows a tree of all files instead of a list.
This makes selecting multiple files at once much easier.
But I follow my no-addons policy very strictly and therefore I need to pass here.&lt;&#x2F;p&gt;
&lt;p&gt;Now I use a
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;99managers-futsal-edition&#x2F;src&#x2F;commit&#x2F;140de94afb52fb2b820530a38724c88479999c8f&#x2F;game&#x2F;src&#x2F;tests&#x2F;test_translations&#x2F;test_translations.gd#L40&quot;&gt;script&lt;&#x2F;a&gt;
to get all .tscn and .gd files and put them into the project.godot file.
It runs every time I run my test suite.
This way, I always have all files covered and I no longer need manual adaptions of the list.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;let-players-know-they-can-help&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#let-players-know-they-can-help&quot; aria-label=&quot;Anchor link for: let-players-know-they-can-help&quot;&gt;Let players know they can help&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The translations will hardly be always complete or correct, especially in early development.
The more it is important to let players know that translation might not be yet 100%.
I show the current translation state of every language in the settings.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;language-picker.webp&quot; alt=&quot;Screenshot of the language picker in 99Managers showing the current translation percentage.&quot;&gt;  
&lt;p&gt;This way players also get informed about Weblate and that they can help with translations.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;choose-you-font-wisely&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#choose-you-font-wisely&quot; aria-label=&quot;Anchor link for: choose-you-font-wisely&quot;&gt;Choose you font wisely&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I never expected that one day someone will translate the whole game into Simplified Chinese.
To my surprise, it did not work instantly after activating the language.
It did work for other languages like Arabic or Ukrainian, that do not have the Latin alphabet.
Then I added
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fonts.google.com&#x2F;noto&#x2F;specimen&#x2F;Noto+Sans+SC&quot;&gt;Noto Sans Simplified Chinese &lt;&#x2F;a&gt;
as &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;ui&#x2F;gui_using_fonts.html#font-fallbacks&quot;&gt;fallback font&lt;&#x2F;a&gt;
and it worked.
This totally makes sense, because the Chinese language has a lot of special characters.
The Chinese one is 17MB big, but my other font is less than 1MB.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;simplified-chinese.webp&quot; alt=&quot;Screenshot of the main dashboard in Chinese.&quot;&gt;  
&lt;p&gt;Just keep this in mind when choosing a font, that might only support Latin alphabet.
But of course this are those things nobody plans for, until it happens.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more-tips-and-tricks&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#more-tips-and-tricks&quot; aria-label=&quot;Anchor link for: more-tips-and-tricks&quot;&gt;More tips and tricks&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you save textual content directly in save games, I recommend to use the base language.
This way it can still be translated to other languages.
I had this issue when I saved all email&#x27;s text in the user defined language.
That way the text could no longer be translated to other languages.
The text would also always stay the same and cannot be changed&#x2F;fixed by an update.
Now I only save a reference id, that safes disk space and allows translations and fixes.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to create .po translation files locally, I recommend the tool
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;poedit.com&quot;&gt;Poedit&lt;&#x2F;a&gt;.
To prevent conflicts I normally do local translations before pushing the .pot template to Weblate.&lt;&#x2F;p&gt;
&lt;p&gt;Keep the base strings simple, verbose and dumb.
Use placeholders only for proper nouns like names if possible.
I tried to reduce needed translations by using a placeholder for the next match location.
The string was &quot;Next {location} match is against {team_name}.&quot;
But apparently in Portuguese {location} cannot simply be replaced by home&#x2F;away.
Home translates to &quot;em casa&quot; but away to &quot;fora&quot;, for reasons (I don&#x27;t speak Portuguese).
Now I use &quot;Next home match is against {team_name}.&quot; and &quot;Next away match is against {team_name}.&quot;
This way it is more work, but allows to translate it correctly.&lt;&#x2F;p&gt;
&lt;p&gt;On Weblate every string can have a screenshot attached, that shows the string in action.
This can help a lot to improve the quality and to provide more context.
I don&#x27;t use them yet, because while developing, screenshots get obsolete very fast.&lt;&#x2F;p&gt;
&lt;p&gt;Once in a while, take some times to check the generated pot file manually.
Sometimes strings get added, that should not.
I had this mysterious bug that all 0 numbers in labels suddenly showed the number 20.
Luckily I discovered that the number 0 got added and somehow translated to 20 in Italian.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;quality-checks-with-weblate&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#quality-checks-with-weblate&quot; aria-label=&quot;Anchor link for: quality-checks-with-weblate&quot;&gt;Quality checks with Weblate&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Weblate checks automatically for many basic translation mistakes.
For example it makes sure that the punctuation and new lines match.
But afaik it can&#x27;t detect if a translation is correct.
This still needs to be done by the players of the game.&lt;&#x2F;p&gt;
&lt;p&gt;Weblate allows to have maintainers&#x2F;moderators that need to approve translations.
My game still has to few contributors that this makes sense.
If the game one day financially succeeds, I will hire professional translators as maintainers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;security&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#security&quot; aria-label=&quot;Anchor link for: security&quot;&gt;Security&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Technically translations can be seen as user generated input.
For this reason I highly recommend reading the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;latest&#x2F;tutorials&#x2F;ui&#x2F;bbcode_in_richtextlabel.html#handling-user-input-safely&quot;&gt;handling user input safely&lt;&#x2F;a&gt;
section in the docs.
Someone could misuse bbcode features, like nested loops and can crash the game.
Even injecting&#x2F;replacing urls is possible.
To mitigate this risks, I have some tests that check all urls in the translations.
I still have to extend this tests to make all bbcode safe.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Showcasing my game at a fair</title>
          <pubDate>Mon, 27 Apr 2026 09:15:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/game-showcase-fair/</link>
          <guid>https://simondalvai.org/blog/game-showcase-fair/</guid>
          <description xml:base="https://simondalvai.org/blog/game-showcase-fair/">&lt;p&gt;I showcased my game &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;99managers.org&quot;&gt;99Managers Futsal Edition&lt;&#x2F;a&gt; already twice.
First at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;godotfest.com&#x2F;&quot;&gt;GodotFest25&lt;&#x2F;a&gt;
in Munich, where everybody could show their game in a dedicated room.
The second time at the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.instagram.com&#x2F;p&#x2F;DT950oUjBUP&#x2F;&quot;&gt;IGDA Trentino Game Night&lt;&#x2F;a&gt;,
similar to GodotFest25.
I really enjoyed both events, especially talking about my open source game.&lt;&#x2F;p&gt;
&lt;p&gt;This year I decided to exhibit at the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.fierabolzano.it&#x2F;it&#x2F;tempo-libero&quot;&gt;Tempo Libero 2026 (IT)&lt;&#x2F;a&gt; &#x2F;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.fierabolzano.it&#x2F;de&#x2F;freizeit&quot;&gt;Freizeit 2026 (DE)&lt;&#x2F;a&gt;,
in the city of Bolzano, Italy.
It is not a fair specific for video games, but generic for leisure time activities and interests.
From sports, camping and food stands to household articles and a gaming court.
Here you can try new sports, buy a lot of stuff and discover new products.&lt;&#x2F;p&gt;
&lt;p&gt;A big thank you to the organizers of the fair for giving free booths to startups, like me!
Without this offer, I would not have attended the fair.&lt;&#x2F;p&gt;
&lt;p&gt;My booth was near the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.fierabolzano.it&#x2F;it&#x2F;tempo-libero&#x2F;event&#x2F;gaming-court&quot;&gt;gaming court&lt;&#x2F;a&gt;,
a 600m² area with a video game exhibition.
From historical game consoles, like NES and SEGA to modern Play 5 or a virtual flipper.
So I was positioned right at the corner of this gaming zone.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;booth-picture.webp&quot; alt=&quot;Picture of my stand at the Freizeit&#x2F;Tempo libero fair in Bolzano, Italy. There are 2 tables with 2 displays and a laptop where my game 99Managers Futsal Edition is running and I stand behind the table.&quot;&gt;  
&lt;p&gt;This is me with my booth the first day, still full of energy :-)&lt;&#x2F;p&gt;
&lt;p&gt;Now I will share my experience and what I learned during this days.
This is no guide but more a personal journal documenting this experience.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;nobody-tried-the-game&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nobody-tried-the-game&quot; aria-label=&quot;Anchor link for: nobody-tried-the-game&quot;&gt;Nobody tried the game&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The hard truth is that in the first 2 days, nobody sat down and played my game.
Some people where interested and asked questions, but never touched the keyboard&#x2F;mouse.&lt;&#x2F;p&gt;
&lt;p&gt;I guess this is related to 2 main reasons.
The first one is that my game is too complicated and niche to just give it a try.
Sport management games have naturally a learning curve and my game is not much intuitive.
Games where you get instant feedback when moving the mouse or joypad might work better.
For example racing games or platformers should perform much better.
Additionally my game is not so visually attracting, being UI heavy with lots of dashboards.&lt;br &#x2F;&gt;
The second reason is that I used a sitting desk as table.
For that reason to play the game, you had to sit or bend down to grab the mouse&#x2F;keyboard.
This might be too much friction for most people that are just curious.
I guess that having a small standing desk would make more people stop and try.&lt;&#x2F;p&gt;
&lt;p&gt;It got better on Saturday and Sunday, where around 30 people actually sat down and played the game.
For the record, there where also a lot more people on the fair those days.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;free-stickers&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#free-stickers&quot; aria-label=&quot;Anchor link for: free-stickers&quot;&gt;Free stickers&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Recently I ordered 1000 stickers of the game logo.
They where meant to be handed out during the fair, but not only.
I did not expect to finish all of them in 4 days.&lt;&#x2F;p&gt;
&lt;img src=&quot;.&#x2F;99managers-futsal-edition-stickers.webp&quot; class=&quot;image image-wide&quot; alt=&quot;Picuter of stickers spread across the table showing the logo with the text &#x27;99MANAGERS FUTSAL EDITION&#x27;&quot;&gt;
&lt;p&gt;Now I still have 850 stickers left, so around 150 stickers where taken.
I hope this will remind people of the game, when they got home.
Stickers are in my opinion better than flyers or cards, because people like stickers.
And they have much more future potential, because they might get attached somewhere very visible.
A lot of people also just grabbed a sticker and moved on.&lt;&#x2F;p&gt;
&lt;p&gt;It would be awesome If I see my sticker attached somewhere in the wild :-)
I&#x27;m also thinking about sending stickers to players around the world.
The main issue with that of course is the high postal fee, but let&#x27;s see.
If you want some stickers, let me know!&lt;&#x2F;p&gt;
&lt;p&gt;The stickers where my only expenses for this fair, since I got the booth for free (thanks again!).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tweaking-the-setup&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tweaking-the-setup&quot; aria-label=&quot;Anchor link for: tweaking-the-setup&quot;&gt;Tweaking the setup&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I changed the my stand setup everyday a little bit, with the observations of the previous day.
For example the first day nearly nobody understood that this was a video game.
Additionally to that, many did not know what the word futsal means, even people who knew the sport.
To be fair, futsal is not much used here, but the Italian and German translations.
(Bolzano is in Italy (South Tyrol), but many here speak German)
For that reasons I created the following simple graphic and showed it on the TV.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;translated-graphic.webp&quot; alt=&quot;The translated graphic shwoing the text in German &#x27;Hallenfußball Management Spiel&#x27; and in Italian &#x27;Gioco managerial calcio a 5&#x27; and &#x27;free stickers&#x27; below. In the center a Steam and Play Store badge.&quot;&gt;  
&lt;p&gt;This translated and explicitly says that it is a game.
Here I learned that it is really important to make people understand what the product is.
It should be clear at first sight.&lt;br &#x2F;&gt;
Next time I will put a big banner saying that it is a video game and the local translations of it.
On the TV instead I could show a trailer of the game, to attract people.&lt;&#x2F;p&gt;
&lt;p&gt;I also removed a laptop and just left the PC where the game could be played and the TV.
It never happened that multiple persons wanted to play at the same time.
And if that would happen, a queue often indicates something interesting, attracting even more.
I also think that having only one possibility to sit down and play is less confusing.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;people-will-see-what-they-want-to-see&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#people-will-see-what-they-want-to-see&quot; aria-label=&quot;Anchor link for: people-will-see-what-they-want-to-see&quot;&gt;People will see, what they want to see&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;It was interesting to hear what some thought my stand was about.
Even after putting the description in both languages on the TV.
The highlights where stickers factory, tournament, tactical software and a real futsal team.&lt;&#x2F;p&gt;
&lt;p&gt;Of course it is mainly my fault, for not making it clear enough.
But I really think with so many people passing by, someone will always see what he wants to see.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-special-demo-mode&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#future-special-demo-mode&quot; aria-label=&quot;Anchor link for: future-special-demo-mode&quot;&gt;(Future) special demo mode&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Showing a futsal match in action attracted the most peoples attention.
But this needed manual intervention from me on game breaks (like half time) and when the match ended.
Additionally most players where disappointed when they tried to play during a match.
There isn&#x27;t much to do during a match and it is better to start from the dashboard.&lt;&#x2F;p&gt;
&lt;p&gt;Having a special demo mode should be much better.
In that mode a match could be run in a loop, without manual intervention (or simply a video).
Once the mouse is touched or a key is pressed, the game exits the demo mode and shows the dashboard.
Maybe even with a nice transition and a message welcoming the player.&lt;&#x2F;p&gt;
&lt;p&gt;For the next fair I really hope to find the time to implement this mode.
This would also allow me to use all displays&#x2F;TVs for promotion and play testing at the same time.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;number-of-sales-during-the-fair&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#number-of-sales-during-the-fair&quot; aria-label=&quot;Anchor link for: number-of-sales-during-the-fair&quot;&gt;Number of sales during the fair&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A crucial metric to measure the success of the fair would be units sold on Steam.
I had no specific link with UTM tracking or whatever to measure this.
But it is currently selling only a few copies a day, therefore I should see changes in local sales.&lt;&#x2F;p&gt;
&lt;p&gt;I checked the Steam sale statistics in Italy, and I sold an amazing amount of 0(!) copies.
The reality is harsh and of course I did expect better results.
But I also hope that many people who saw the game might buy it in the future.
Or at least share it with friends and fellow futsal followers.
There is also to say that most people did not know what Steam is.
Finding gamers that know Steam and enjoy futsal was harder than expected.&lt;&#x2F;p&gt;
&lt;p&gt;So while the short-term results are really bad, long term it might bring something.
I met some real futsal players and they where really excited about the game.
At least I got some visibility at the local futsal communities.&lt;&#x2F;p&gt;
&lt;p&gt;Anyways I learned a lot and knowledge is priceless ;-)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-thoughts&quot; aria-label=&quot;Anchor link for: final-thoughts&quot;&gt;Final thoughts&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The fair started as a flop but turned out great in the end.
I was able to show my game to people playing futsal and hopefully attracted new players.
I also learned a lot about how to promote a product directly to people.
Staying alone for 10 hours at a booth for 4 days is a bit too much, but possible.
I just needed at least 1 day of rest afterwards.&lt;&#x2F;p&gt;
&lt;p&gt;Opportunities like this help a lot to get experience and free marketing.
Usually stands cost hundreds or thousands Euros and more.
If you happen to get a free or low-cost spot somewhere, go for it!&lt;&#x2F;p&gt;
&lt;p&gt;I&#x27;m already keeping my eyes open for other fairs nearby (North Italy) :-)
If you happen to know something interesting, let me know!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>My split keyboard journey</title>
          <pubDate>Mon, 23 Mar 2026 16:30:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/split-keyboard-journey/</link>
          <guid>https://simondalvai.org/blog/split-keyboard-journey/</guid>
          <description xml:base="https://simondalvai.org/blog/split-keyboard-journey/">&lt;p&gt;In January 2025 I got my first split keyboard.
After seeing so many Vim&#x2F;Neovim video content creators use them, I also wanted to try.
Now more than a year later, I&#x27;m happy to share my experience with it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;corne-v4&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#corne-v4&quot; aria-label=&quot;Anchor link for: corne-v4&quot;&gt;corne v4&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I just wanted to try if split keyboards work for me.
My first attempt was to buy a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;foostan&#x2F;crkbd&quot;&gt;corne v4&lt;&#x2F;a&gt;.
It seemed one of the most popular split keyboards I found online.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;corne.webp&quot; alt=&quot;corne keyboard with black keycaps&quot;&gt;  
&lt;p&gt;I bought a pre-built version, so I could just plug it in and use it.
This one even has RGB lights under the switches, but I never really used them.
I actually ordered it without RGB, to save money, but somehow I got it anyways.&lt;&#x2F;p&gt;
&lt;p&gt;Sometimes one half of the corne randomly stops working.
I assume this is related to
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;foostan&#x2F;crkbd?tab=readme-ov-file#notice&quot;&gt;electromagnetic inference&lt;&#x2F;a&gt;.
I just have to reconnect to fix the problem, so it is not a big deal.
But this shows what complex issues hardware can face (and why I love writing software instead).&lt;&#x2F;p&gt;
&lt;p&gt;I bought it with empty key-caps, because my goal was to learn touch typing.
I never really tried that before and I wanted to write without looking at the keyboard.
It worked!
Now I can type without looking and my current words per minute record is 95.&lt;&#x2F;p&gt;
&lt;p&gt;For what I saw online, split keyboards normally cost from 100€ to 300€.
But it highly depends on the amount of keys and the materials used.
Sometimes only the case made of aluminium, can cost more than 100€.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;alternative-layouts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#alternative-layouts&quot; aria-label=&quot;Anchor link for: alternative-layouts&quot;&gt;Alternative layouts&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Changing to a split keyboard is already a big change to get used to.
Also changing the layout makes it even harder to make the switch.
But I had to learn to touch type qwerty anyways from scratch, so why not try something better?
So after a few days with qwerty, I decided to try colemak-dh.&lt;&#x2F;p&gt;
&lt;p&gt;I really like colemak-dh and it makes writing English a real joy.
So many words can be written with never leaving the home row.
On the long run, it should also increase typing speed and reduce finger movements.&lt;&#x2F;p&gt;
&lt;p&gt;I even tried to change layout on my smartphone to memorize the letter positions faster.
But a quick web search revealed that is makes not much sense for two reasons:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;A different (thumbs) muscle memory is used with touch screens&lt;&#x2F;li&gt;
&lt;li&gt;On small screens having more space between frequent used keys actually makes&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;train-everyday&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#train-everyday&quot; aria-label=&quot;Anchor link for: train-everyday&quot;&gt;Train everyday&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Training is needed to overcome the first &lt;em&gt;really&lt;&#x2F;em&gt; frustrating days.
Writing at 10 words per minute is not fun and my productivity dropped a lot.
There are tons of websites and tools that can help with that.&lt;&#x2F;p&gt;
&lt;p&gt;I did all my training on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;keybr.com&quot;&gt;keybr.com&lt;&#x2F;a&gt;.
This site is really great and starts with the home row first.
New keys unlock when a set writing speed is reached and so the muscle memory builds up consistently.&lt;&#x2F;p&gt;
&lt;p&gt;In my opinion there are two ways to learn to touch type on a new keyboard&#x2F;layout&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Only use the new keyboard&#x2F;layout and hope that you don&#x27;t give up&#x2F;get too frustrated&lt;&#x2F;li&gt;
&lt;li&gt;Train only 30 minutes a day and keep working with the old keyboard&#x2F;layout&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;The second one might be the most reasonable and allows to improve slowly without loosing sanity.
Once a certain speed is reached, you can try to use it everywhere.&lt;&#x2F;p&gt;
&lt;p&gt;I personally did both by always using the new keyboard and train at least 30 mins a day.
The first days where hard and I kept a normal keyboard close for critical situations.
But overall this is the fastest way to do the switch.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yes-i-still-can-use-normal-keyboards&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#yes-i-still-can-use-normal-keyboards&quot; aria-label=&quot;Anchor link for: yes-i-still-can-use-normal-keyboards&quot;&gt;Yes, I still can use normal keyboards&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Many people that saw my split keyboard had the question if I still can type on normal keyboards.
I built up new muscle memory for split keyboards, so the other remained untouched.
I still write the same way and speed on normal keyboards as I used before.
Of course quite slow and by looking while typing, but nothing changed there.&lt;&#x2F;p&gt;
&lt;p&gt;Probably it gets more difficult if you want to change layout on the same keyboard.
There the old muscle memory needs to be &quot;re-wired&quot; and that can be more tricky.
And the old muscle memory will partially be erased.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;dasbob&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#dasbob&quot; aria-label=&quot;Anchor link for: dasbob&quot;&gt;DASBOB&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;After 9 months of using the corne, I decided to try another split keyboard.
I wanted less keys, a more aggressive pinky stagger and a more outwards positioned thumb cluster.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;dasbob.webp&quot; alt=&quot;DASBOB keyboard with white keycaps&quot;&gt;  
&lt;p&gt;I was undecided between the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;davidphilipbarr&#x2F;Sweep&quot;&gt;Sweep&lt;&#x2F;a&gt; and
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GroooveBob&#x2F;DASBOB&quot;&gt;DASBOB&lt;&#x2F;a&gt;.
In the end I bought DASBOB to keep the 3 thumb keys.
DASBOB even has a buzzer that can make sounds!&lt;&#x2F;p&gt;
&lt;p&gt;This time I bought a DIY kit, so I had to solder the switches and micro controller myself.
While this takes more time, it was a nice feeling to have built it myself.
For a moment I even considered to print the PCB and the case from a PCB manufacturer.
But import and shipping costs are too high for a single PCB and case.
This is possible because most split keyboards are open source and open hardware.
The pcb layouts and firmware are shared and therefore can be printed and modified by anyone.
Maybe for my next keyboard I will try that :-)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;vial&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#vial&quot; aria-label=&quot;Anchor link for: vial&quot;&gt;Vial&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To configure my keyboards I use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;get.vial.today&#x2F;&quot;&gt;Vial&lt;&#x2F;a&gt;.
This allows to configure everything in real-time with a nice GUI.&lt;&#x2F;p&gt;
&lt;p&gt;Currently I use 6 layers, but I plan to reduce the layer amount soon.&lt;&#x2F;p&gt;
&lt;p&gt;Layer 1 with the colemak-dh layout letters.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;dasbob-layer1.webp&quot; alt=&quot;DASBOB Layer 1&quot;&gt;  
&lt;p&gt;Layer 2 with numbers and navigation.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;dasbob-layer2.webp&quot; alt=&quot;DASBOB Layer 2&quot;&gt;  
&lt;p&gt;Layer 3 with symbols and navigation.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;dasbob-layer3.webp&quot; alt=&quot;DASBOB Layer 3&quot;&gt;  
&lt;p&gt;Layer 4 has turns on DASBOB&#x27;s buzzer and some mouse clicks.
I have this layer just for fun and rarely use it.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;dasbob-layer4.webp&quot; alt=&quot;DASBOB Layer 4&quot;&gt;  
&lt;p&gt;Layer 5 has all F-keys, volume and brightness control.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;dasbob-layer5.webp&quot; alt=&quot;DASBOB Layer 5&quot;&gt;  
&lt;p&gt;Layer 6 instead is my sway-wm layer, that allows me to change workspace with one hand.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;dasbob-layer6.webp&quot; alt=&quot;DASBOB Layer 6&quot;&gt;  
&lt;p&gt;I guess one day I will try &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;qmk.fm&#x2F;&quot;&gt;QMK&lt;&#x2F;a&gt;, simply to see what the differences are.
For now it seems to me, that QMK is much more powerful and allows to code a custom firmware in C.
That sounds really cool!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tenting&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tenting&quot; aria-label=&quot;Anchor link for: tenting&quot;&gt;Tenting&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Around the time I bought DASBOB, I also started tenting the keyboard, for a natural hand position.
Since I got used to tenting, writing on a flat keyboard just feels wrong&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;dasbob-tenting.webp&quot; alt=&quot;DASBOB with tenting&quot;&gt;  
&lt;p&gt;There are many ways to do tenting.
First, I simply used an open book in the center, to feel if tenting works for me.
Then I bought two phone stands that have magnetic rings on both sides and attached jar lids.
At the bottom of the jar lids I attached some rubber feet to prevent slipping.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;dasbob-tenting-base.webp&quot; alt=&quot;The base used for tenting&quot;&gt;  
&lt;p&gt;For some time I even had metal rings attached on my laptop.
Here you can get really creative and I saw a lot of unique setups on the web.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;switches&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#switches&quot; aria-label=&quot;Anchor link for: switches&quot;&gt;Switches&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The corne has Kailh Choc v1 brown switches.
I would say it was a good choice, for my first mechanical switches.
They are not too loud and the key press feels good and not too heavy.&lt;&#x2F;p&gt;
&lt;p&gt;For the DASBOB instead, I bought Kailh Low Ambients Silent Twilight switches and I really like them.
They are more silent, linear of course and much lighter to press.
Sometimes even too light.
For example in the train I accidentally pressed keys when the train bumped.
But aside from this, they are awesome and now the browns feel too heavy for me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-keyboard-wishlist&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-keyboard-wishlist&quot; aria-label=&quot;Anchor link for: my-keyboard-wishlist&quot;&gt;My keyboard wishlist&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;While I&#x27;m really happy with my DASBOB, out of curiosity I want to explore more variations.
I would love to try concave shapes like the Kinesis Advantage, the Glove80 or the Dactyl have.
This keyboards also have a tilted thumb cluster where thumb key presses movements are more natural.
With normal thumb clusters the thumbs need to make a side wards movement to press keys.&lt;&#x2F;p&gt;
&lt;p&gt;Another cool thing would be a laptop with an integrated split keyboard.
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;frame.work&#x2F;at&#x2F;en&#x2F;products&#x2F;one-key-module&quot;&gt;Framework&lt;&#x2F;a&gt;
has now a one key module, that allows to build custom keyboards.
The Reform Next has a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;funnes&#x2F;reform-split-keyboard&quot;&gt;cool prototype&lt;&#x2F;a&gt;
that would be nearly perfect.
Projects like this show why and how open hardware is so interesting and important.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>I Love Free Software Day 2026</title>
          <pubDate>Sat, 14 Feb 2026 22:13:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/ilovefs-day-2026/</link>
          <guid>https://simondalvai.org/blog/ilovefs-day-2026/</guid>
          <description xml:base="https://simondalvai.org/blog/ilovefs-day-2026/">&lt;p&gt;Also this year I want to celebrate &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fsfe.org&#x2F;activities&#x2F;ilovefs&#x2F;&quot;&gt;I Love Free Software Day&lt;&#x2F;a&gt;.
Thanks to the whole FOSS community for another year of open software and knowledge sharing!&lt;&#x2F;p&gt;
&lt;p&gt;Now to the three project I want to thank this year &amp;lt;3&lt;&#x2F;p&gt;
&lt;h2 id=&quot;end-of-10&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#end-of-10&quot; aria-label=&quot;Anchor link for: end-of-10&quot;&gt;End of 10&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This year I made it even more special, by installing Debian on my moms laptop.
The main reason for this was that I had the choice between updating Windows 11 or installing Linux.
I did not even check if the laptop supports Windows 11 or if it was supposed to become e-trash.
I no longer use Windows since many many happy years, except in some VMs to try my developed games.
But reading all the (bad) news about AI and spyware in Windows, the choice was easy.
Time will tell if my mom will like it or not, but I guess it will be fine.
I already installed Ubuntu on her old laptop a few years ago and getting some extra years out of it.&lt;&#x2F;p&gt;
&lt;p&gt;Help your family an friends to free their devices and get more years out of them!
You can find more info on how to switch from Windows to Linux on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;endof10.org&#x2F;&quot;&gt;End of 10&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;inkscape&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#inkscape&quot; aria-label=&quot;Anchor link for: inkscape&quot;&gt;Inkscape&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The last months I learned more about Inkscape and how to use it.
I really like the design, functionality and how easy it is to draw nice looking graphics.
Most of my graphical works for my latest game &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;99managers.org&quot;&gt;99managers.org&lt;&#x2F;a&gt;
where made with it.
I really like how the new logo and the background in the game turned out!&lt;&#x2F;p&gt;
&lt;p&gt;To support Inkscape, you can &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;inkscape.org&#x2F;support-us&#x2F;donate&#x2F;&quot;&gt;donate&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;inkscape.org&#x2F;contribute&#x2F;&quot;&gt;contribute&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;neovim&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#neovim&quot; aria-label=&quot;Anchor link for: neovim&quot;&gt;Neovim&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Neovim is now my main editor and I use it for everything.
It is amazing to see how modal editors can make typing text fun and a challenge.
Complex modifications can be done in a few keystrokes and macros can do all the rest.
Now I never want to leave the terminal again.&lt;&#x2F;p&gt;
&lt;p&gt;Here you can &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;neovim.io&#x2F;sponsors&#x2F;&quot;&gt;donate&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&quot;&gt;contribute&lt;&#x2F;a&gt;
to Neovim.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Steam Auto-Cloud cross-platform save game synchronization</title>
          <pubDate>Sat, 24 Jan 2026 22:50:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/save-game-sync/</link>
          <guid>https://simondalvai.org/blog/save-game-sync/</guid>
          <description xml:base="https://simondalvai.org/blog/save-game-sync/">&lt;p&gt;I recently added cross platform save game synchronization to my game.
It is designed to work with the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;partner.steamgames.com&#x2F;doc&#x2F;features&#x2F;cloud#steam_auto-cloud&quot;&gt;Steam Auto-Cloud&lt;&#x2F;a&gt;,
without using the SteamSDK.
Therefore no SteamSDK specific code is needed in the game.
This make the game compatible also with other file synchronization software, such as
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;syncthing.net&#x2F;&quot;&gt;Syncthing&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;My game is Open Source and APLv3 licensed and that makes it incompatible with the SteamSDK anyways.
This way I can release a copyleft game on Steam with the minimum Cloud Sync support.
It is made with the Godot Engine 4.x, but I will not show any code here.
A save game implementation is in most cases too specific for a game.
It simply makes more sense to just show the overall idea behind it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-should-be-synced&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-should-be-synced&quot; aria-label=&quot;Anchor link for: what-should-be-synced&quot;&gt;What should be synced&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;First of course, &lt;strong&gt;all save game files&lt;&#x2F;strong&gt; that contain game progress need to be synchronized.
This are the most important files and they should be handled with care.
Nobody wants to loose progress and restart from the beginning.&lt;&#x2F;p&gt;
&lt;p&gt;Some other files instead, should &lt;strong&gt;always be excluded&lt;&#x2F;strong&gt;, like&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;log files&lt;&#x2F;li&gt;
&lt;li&gt;caches&lt;&#x2F;li&gt;
&lt;li&gt;...other temporary files your game&#x2F;engine produces&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;It also makes sense to &lt;strong&gt;divide user settings&lt;&#x2F;strong&gt; into local only and synchronized.
Settings that should be synced are&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;language&lt;&#x2F;li&gt;
&lt;li&gt;internationalization settings, such as date formats, currencies...&lt;&#x2F;li&gt;
&lt;li&gt;specific game settings, such as camera movements or auto-save&lt;&#x2F;li&gt;
&lt;li&gt;...whatever a user expects to set only once&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Settings that should not be synced are&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;screen resolution&lt;&#x2F;li&gt;
&lt;li&gt;full screen mode&lt;&#x2F;li&gt;
&lt;li&gt;input mappings and settings, like key mapping or if a joypad is preferred&lt;&#x2F;li&gt;
&lt;li&gt;...and all other device specific settings&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;For some settings it can get difficult to decide if they are local or synced.
A good example for this is the UI theme.
A user might prefer dark themes on the SteamDeck OLED screen, to save battery.
But uses light themes on all other devices.
In this special cases, it could make sense to let the user decide, if a specific setting is synced.
This could be a simple checkbox that enables&#x2F;disables the sync between devices.&lt;&#x2F;p&gt;
&lt;p&gt;In summary &lt;em&gt;all&lt;&#x2F;em&gt; save game files, but only &lt;em&gt;some&lt;&#x2F;em&gt; settings, should be synchronized.
This is the basic and simplified structure of the user directory of my game (on Linux).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.local&#x2F;share&#x2F;99managers-futsal-edition&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    local&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        settings_local.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        version.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sync&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        deleted_save_games.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        settings_sync.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        save_games&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            136907-518000-261045&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                checksums.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                cups.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                inbox.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                leagues.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Everything in the &lt;strong&gt;sync&lt;&#x2F;strong&gt; directory gets synchronized.
This makes it easy to setup synchronization, because the whole directory is affected.
It contains the sync settings and all save game files.
The deleted save games file is the only special file Steam needs and I will explain its use later.&lt;&#x2F;p&gt;
&lt;p&gt;Off topic: you might ask yourself why the hell I use csv files?
Well, I tried a lot of formats like ini files, Godot Resources and json files.
But the ability to let also non-developers inspect them with tools they know convinced me.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;atomic-saving-and-backups&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#atomic-saving-and-backups&quot; aria-label=&quot;Anchor link for: atomic-saving-and-backups&quot;&gt;Atomic saving and backups&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Crashes or other unexpected terminations of the game while saving can lead to corrupted files.
The more time it takes to save the state to disk, the higher the probability that this will happen.
For that reason it makes sense to implement atomic saves.&lt;&#x2F;p&gt;
&lt;p&gt;Instead of overwriting directly the current save files, they are written to new staging files.
So if the save process is interrupted, the real save files stay untouched.
Once all files are written to disk, you overwrite the real save files with the staging ones.&lt;&#x2F;p&gt;
&lt;p&gt;To be even more safe and fail proof, you can add backups to the atomic save cycle.
This can be achieved by simply renaming the active save to something else, before overwriting it.&lt;&#x2F;p&gt;
&lt;p&gt;In my case I even save two backups of every file I save to disk.
So the atomic save process with double backups is the following&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;write all files to staging&#x2F;&lt;&#x2F;li&gt;
&lt;li&gt;rename backup1&#x2F; to backup2&#x2F;&lt;&#x2F;li&gt;
&lt;li&gt;rename active&#x2F; to backup1&#x2F;&lt;&#x2F;li&gt;
&lt;li&gt;rename staging&#x2F; to active&#x2F;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Note: The second step can be skipped, if a single backup is enough.
If something goes wrong in a step, there are still backups from where the user can recover.&lt;&#x2F;p&gt;
&lt;p&gt;With this approach my user directory looks like this&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;.local&#x2F;share&#x2F;99managers-futsal-edition&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    local&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        settings_local.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        settings_local.csv.backup1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        settings_local.csv.backup2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        version.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    sync&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        deleted_save_games.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        deleted_save_games.csv.backup1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        deleted_save_games.csv.backup2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        settings_sync.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        settings_sync.csv.backup1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        settings_sync.csv.backup2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        save_games&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;            136907-518000-261045&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                active&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    checksums.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    cups.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                backup1&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    checksums.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    cups.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                backup2&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    checksums.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    cups.csv&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                    ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This of course increases the total disk usage of the user directory.
But it makes a really robust and fail proof save process.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;corruption-detection&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#corruption-detection&quot; aria-label=&quot;Anchor link for: corruption-detection&quot;&gt;Corruption detection&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now I still need to figure out if a file has been corrupted.
For that I use a checksums file, that contains the sha256 sum of every file, after it was saved.
Every save state has it&#x27;s own checksums file.
Before loading a file, I check that it still has the correct sha256 sum.
If a save game file is corrupted, I let the user decide, if a backup should be loaded.
I let the user also skip the checksum validation, in case files where modified intentionally.&lt;&#x2F;p&gt;
&lt;p&gt;It is important to know that Steam Auto-Cloud does not synchronize empty files.
For that reason I also save empty files to that list, with the sha256 sum of an empty string:&lt;&#x2F;p&gt;
&lt;p&gt;e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855&lt;&#x2F;p&gt;
&lt;p&gt;If a file from the checksum list is not found, I can check if it should be empty.
A simple boolean flag, that is true if the file is empty, would actually also do the job.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;steam-auto-cloud&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#steam-auto-cloud&quot; aria-label=&quot;Anchor link for: steam-auto-cloud&quot;&gt;Steam Auto-Cloud&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now that you know what needs to be synced and how to securely safe files, you can synchronize them.&lt;br &#x2F;&gt;
To use the Steam Auto-Cloud feature, it needs to be enabled for your game.
How this is done might change in future, so it does not make any sense to write it down here.
Just follow the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;partner.steamgames.com&#x2F;doc&#x2F;features&#x2F;cloud&quot;&gt;official documentation&lt;&#x2F;a&gt;,
that (hopefully) will always be updated and have the correct information.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;cross-platform-configuration&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#cross-platform-configuration&quot; aria-label=&quot;Anchor link for: cross-platform-configuration&quot;&gt;Cross platform configuration&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Once it is enabled, you can decide what directories get synced between devices.
To do that, you need to set a root path with root overrides for the other operating systems.
Because Windows still has the biggest market share on Steam, it makes sense to make Windows root.&lt;&#x2F;p&gt;
&lt;p&gt;Set the following configuration at Steamworks &amp;gt; App Data Admin &amp;gt; Application &amp;gt; Steam Cloud.&lt;&#x2F;p&gt;
&lt;h4 id=&quot;root-paths-windows&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#root-paths-windows&quot; aria-label=&quot;Anchor link for: root-paths-windows&quot;&gt;Root paths (Windows)&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;Root&lt;&#x2F;strong&gt; WinAppDataRoaming&lt;br &#x2F;&gt;
&lt;strong&gt;Subdirectory&lt;&#x2F;strong&gt; 99managers-futsal-edition\sync\&lt;br &#x2F;&gt;
&lt;strong&gt;Pattern&lt;&#x2F;strong&gt; *&lt;br &#x2F;&gt;
&lt;strong&gt;OS&lt;&#x2F;strong&gt; All OSes&lt;br &#x2F;&gt;
&lt;strong&gt;Recursive&lt;&#x2F;strong&gt; Yes&lt;br &#x2F;&gt;
&lt;strong&gt;Cross platform&lt;&#x2F;strong&gt; Yes&lt;&#x2F;p&gt;
&lt;h4 id=&quot;root-overrides-linux&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#root-overrides-linux&quot; aria-label=&quot;Anchor link for: root-overrides-linux&quot;&gt;Root overrides (Linux)&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;Original root&lt;&#x2F;strong&gt; WinAppDataRoaming&lt;br &#x2F;&gt;
&lt;strong&gt;OS&lt;&#x2F;strong&gt; Linux + SteamOS&lt;br &#x2F;&gt;
&lt;strong&gt;New root&lt;&#x2F;strong&gt; LinuxXdgDataHome&lt;br &#x2F;&gt;
&lt;strong&gt;Add&#x2F;Replace path&lt;&#x2F;strong&gt; 99managers-futsal-edition&#x2F;sync&#x2F;&lt;br &#x2F;&gt;
&lt;strong&gt;Replace path&lt;&#x2F;strong&gt; Yes&lt;&#x2F;p&gt;
&lt;h4 id=&quot;root-overrides-macos&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#root-overrides-macos&quot; aria-label=&quot;Anchor link for: root-overrides-macos&quot;&gt;Root overrides (MacOS)&lt;&#x2F;a&gt;&lt;&#x2F;h4&gt;
&lt;p&gt;&lt;strong&gt;Original root&lt;&#x2F;strong&gt; WinAppDataRoaming&lt;br &#x2F;&gt;
&lt;strong&gt;OS&lt;&#x2F;strong&gt; MacOS&lt;br &#x2F;&gt;
&lt;strong&gt;New root&lt;&#x2F;strong&gt; MacHome&lt;br &#x2F;&gt;
&lt;strong&gt;Add&#x2F;Replace path&lt;&#x2F;strong&gt; &#x2F;Library&#x2F;Application Support&#x2F;99managers-futsal-edition&#x2F;sync&#x2F;&lt;br &#x2F;&gt;
&lt;strong&gt;Replace path&lt;&#x2F;strong&gt; Yes&lt;&#x2F;p&gt;
&lt;p&gt;To make this platform specific instead, simply use a dedicated root path for every OS.
The files would be synced only between devices with the same OS.&lt;&#x2F;p&gt;
&lt;p&gt;Note: This setup is specific for my game made with Godot Engine 4.
Other engines might use different directories to save user files.
Anyway the way to organize the root directories should remain the same.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;deleting-save-games&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#deleting-save-games&quot; aria-label=&quot;Anchor link for: deleting-save-games&quot;&gt;Deleting save games&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Steam does not delete files or directories on other devices.
This means if you delete a save game on a device, it will still exist on the other devices.
My game scans the save directory for files, so a deleted state would show up again on another device.
For that the deleted save games file is needed, to make sure that they get deleted everywhere.&lt;&#x2F;p&gt;
&lt;p&gt;My deleted save games file contains the ids of deleted save states.
If a save state with a deleted id is scanned, it gets moved to the trash.
Alongside every deleted id, I also save the time stamp of the deletion.
That allows to periodically remove all ids that are older than one year.&lt;br &#x2F;&gt;
Note: This is only needed for Steam Auto-Cloud.
Syncthing for example can delete files between devices, if configured to do so.&lt;&#x2F;p&gt;
&lt;p&gt;I never permanently delete files, but move them to the operating systems trash.
This assures that in most cases everything can be recovered from there.
If you want to have 100% file recovery, a custom trash directory can help.
Deleted files get moved to the custom trash and then the user empties that trash manually.
This would also work where no trash system exists, such as web or iOS.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sync-conflicts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#sync-conflicts&quot; aria-label=&quot;Anchor link for: sync-conflicts&quot;&gt;Sync conflicts&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The Steam client will inform the user, when a conflict happens.
The user can choose what save state to keep, by looking at the last modified time stamp.
This means no special logic is needed inside the game.&lt;&#x2F;p&gt;
&lt;p&gt;The Steam client triggers the sync before a game is opened and after it is closed.
Most conflicts happen if the sync failed, because of missing network connection.
Or if a game is played simultaneously on different devices, but that is less common.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;steam-auto-cloud-vs-cloud-api&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#steam-auto-cloud-vs-cloud-api&quot; aria-label=&quot;Anchor link for: steam-auto-cloud-vs-cloud-api&quot;&gt;Steam Auto-Cloud vs Cloud API&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The Steam Cloud API has more features, than the simple Auto-Cloud.
It brings fine-grained sync support, where you can choose which file gets synced when.
The Auto-Cloud simply synchronizes the states when the game is opened and when it&#x27;s closed.
The API instead can upload and download files, while the game is running.
This adds interesting features for the Steam Deck, like
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;partner.steamgames.com&#x2F;doc&#x2F;features&#x2F;cloud#dynamic_cloud_sync&quot;&gt;Dynamic Cloud Sync&lt;&#x2F;a&gt;.
This allows to suspend a game, continue on another device and then resume again on the Steam Deck.
Of course, without losing any progress by synchronizing all files that changed in the meantime.&lt;&#x2F;p&gt;
&lt;p&gt;Implementing such features require the SteamSDK and lot of sync logic in the game.
But I guess it depends on the type of the game what type of Cloud sync makes sens.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;great-now-the-code-please&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#great-now-the-code-please&quot; aria-label=&quot;Anchor link for: great-now-the-code-please&quot;&gt;Great, now the code please&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you want to see how I implemented this in my game, check out the repository on
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;99managers-futsal-edition&quot;&gt;Codeberg&lt;&#x2F;a&gt;.
Just poke around the game&#x2F;src&#x2F; directory and you should find the code where all this happens.&lt;&#x2F;p&gt;
&lt;p&gt;To see the code in action, get the game on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;99managers.org&#x2F;&quot;&gt;99managers.org&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>3 years of blogging</title>
          <pubDate>Mon, 29 Dec 2025 20:15:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/3-years-blogging/</link>
          <guid>https://simondalvai.org/blog/3-years-blogging/</guid>
          <description xml:base="https://simondalvai.org/blog/3-years-blogging/">&lt;p&gt;On this exact day 3 years ago, I published my first blog post.
Then, I published a new blogpost every month to a total of 38 posts.&lt;br &#x2F;&gt;
Enjoy the last post of 2025 about the blog itself!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-better-at-writing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#getting-better-at-writing&quot; aria-label=&quot;Anchor link for: getting-better-at-writing&quot;&gt;Getting better at writing&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A big goal when I started this was to get better at writing in English.
I think over the time my writing got better.
I make less mistakes and can structure my thoughts better into words and sections.
This makes writing much more enjoyable, because now I can focus on what to write.
I still make mistakes of course, but in the days of LLMs that makes a blog human, I guess ;-)&lt;&#x2F;p&gt;
&lt;p&gt;In the meantime I started also writing some small devlogs for my game
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;99managers.org&#x2F;blog&#x2F;&quot;&gt;99Managers&lt;&#x2F;a&gt;.
Having 3 years of &quot;blogging experience&quot; gives me the confidence to write more and more.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-tracking-needed&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#no-tracking-needed&quot; aria-label=&quot;Anchor link for: no-tracking-needed&quot;&gt;No tracking needed&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I do not use any form of tracking on this website or any other software I publish.
Technically, I can see the Caddy web server logs, but also there I just see what files are accessed.
Therefore I cannot really distinguish between bots and normal users.&lt;&#x2F;p&gt;
&lt;p&gt;So I use the Google Search Console to see what gets the most impressions and clicks on Google.
This works for every site and just needs a TXT DNS entry to verify ownership of the website.
Google tracks the traffic of their search engine anyways and for me this data is enough.
I don&#x27;t have and want to analyze graphs and statistics to understand what readers like.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway the best feedback comes directly from the readers.
No graph can say &quot;thank you for writing this&quot; or &quot;here I found some cool stuff related to your post&quot;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-cookie-banner-needed&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#no-cookie-banner-needed&quot; aria-label=&quot;Anchor link for: no-cookie-banner-needed&quot;&gt;No cookie banner needed&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I am not a lawyer, so do your own research before blindly believing the next paragraph.&lt;&#x2F;p&gt;
&lt;p&gt;This website does not need any cookie banner or GDPR notice, as far as I understood.
No personal data is collected, because my Caddy logs drop all personal information.
No IP-Address, user-agent or anything similar is collected.
Only the requested file, the time-stamp and the HTTP response code are logged.
I also don&#x27;t use any third party css or fonts that would expose the readers IP to third parties.
And of course, no JavaScript or anything that could communicate over the network runs here.&lt;&#x2F;p&gt;
&lt;p&gt;If you use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gorhill&#x2F;uBloc&quot;&gt;uBlock Origin&lt;&#x2F;a&gt;, you can see that nothing gets blocked
here.
There are not many websites that do not trigger any uBlock block, but they exist:
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lichess.org&#x2F;&quot;&gt;Lichess&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;&quot;&gt;Mastodon&lt;&#x2F;a&gt; are my favorite
examples.&lt;&#x2F;p&gt;
&lt;p&gt;Nowadays cookie and consent banners are so invasive and omnipresent, that most don&#x27;t know that you
can run a website without them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-best-posts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-best-posts&quot; aria-label=&quot;Anchor link for: my-best-posts&quot;&gt;My best posts&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;According to the Google Search Console my best posts are the following&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;debian-sway-v1&#x2F;&quot;&gt;Debian Sway v1 - My first setup&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;godot-neovim&#x2F;&quot;&gt;Neovim as External Editor for Godot&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;godot-vs-libgdx&#x2F;&quot;&gt;Godot Engine vs libGDX&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Like in every other search optimized ecosystem, niche content gets the most traction.
There is not much on the web about using SwayWM on Debian or Neovim with Godot.
So sharing whatever niche things you use or work on could make sense, if you care about visibility.&lt;&#x2F;p&gt;
&lt;p&gt;But I do not really care about what performs best, it&#x27;s just interesting to see, sometimes.
If I would care too much, the chase for the next niche article would ruin everything.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;own-your-place-on-the-web&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#own-your-place-on-the-web&quot; aria-label=&quot;Anchor link for: own-your-place-on-the-web&quot;&gt;Own your place on the web&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Having a personal website or a blog means that you can control a small part of the web.
With control, I mean real full control.
Using social media or any other type of third party platform brings some risks.
Let&#x27;s put aside all the privacy issues (except Mastodon &amp;lt;3) and ethical problems.
One day the platform will become old and people move to a new one.
Or it changes policies and you have no longer access to your account.
[Put any social media platform here] will be obsolete in x years.
Your website not.
There are many other reasons, having full control of your space is important.&lt;&#x2F;p&gt;
&lt;p&gt;With your own blog you can also shape the web a little bit in the direction you want.
For example by choosing to not use any tracking and make weird looking websites.
I really have to improve on that, my website looks too boring ;-)
I was and am still a big fan of &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;brutalistwebsites.com&#x2F;&quot;&gt;brutalistwebsites&lt;&#x2F;a&gt;.
Maybe this site gets more brutal too one day.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hetzner-debian-caddy-zola&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#hetzner-debian-caddy-zola&quot; aria-label=&quot;Anchor link for: hetzner-debian-caddy-zola&quot;&gt;Hetzner + Debian + Caddy + Zola&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is my tech stack for all my current websites.
In my opinion, having a simple stack is really important.
It needs less maintenance, has less problems and will work for longer.&lt;&#x2F;p&gt;
&lt;p&gt;The best choice I made in my opinion is to use a static site builder, like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;Zola&lt;&#x2F;a&gt;.
I chose Zola because I already knew &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;&quot;&gt;Hugo&lt;&#x2F;a&gt;, but found Hugo too bloated.
Everything is written in Markdown and converted to static HTML files, served by Caddy.
If one day I want to switch to another tool, I can simply move the markdown content there.&lt;&#x2F;p&gt;
&lt;p&gt;As webserver I chose &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;Caddy&lt;&#x2F;a&gt;, because I used it in other projects at work.
It has an easy SSL setup, with LetsEncrypt and I never had any issues or crashes yet.
It might take some time to setup correctly the first time, but once it runs it is a pleasure.&lt;&#x2F;p&gt;
&lt;p&gt;All mentioned above runs on Debian on the cheapest Hetzner VPS currently available.
I never had any issues with this setup.
To note that I started this website on Github Pages and switched to Hetzner on
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@dulvui&#x2F;111428466369499053&quot;&gt;18 November 2023&lt;&#x2F;a&gt;.
The CPU usage rarely goes beyond 5% and the 20TB of traffic included are really enough.
I rarely reach a 10GB per month, but I do not host videos and make sure all images are webp.&lt;&#x2F;p&gt;
&lt;p&gt;Oh I nearly forgot: I deploy everything with a simple rsync command.
No CI or similar can beat the simplicity of one single command.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-words&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-words&quot; aria-label=&quot;Anchor link for: final-words&quot;&gt;Final words&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Thank you all for reading this and all other posts during the last 3 years!
I hope you enjoyed it and start to create your own space on the web too, if you haven&#x27;t already.&lt;&#x2F;p&gt;
&lt;p&gt;All the best,&lt;br &#x2F;&gt;
Simon&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>[Talk] SFSCON 2025: Making a sport management game in Godot</title>
          <pubDate>Tue, 25 Nov 2025 09:40:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/sfscon-2025-99managers/</link>
          <guid>https://simondalvai.org/blog/sfscon-2025-99managers/</guid>
          <description xml:base="https://simondalvai.org/blog/sfscon-2025-99managers/">&lt;p&gt;During the 7 and 8 November I attended again &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.sfscon.it&#x2F;&quot;&gt;SFSCON 2025&lt;&#x2F;a&gt;.
This was the 25th Edition of the conference about Free and Open Source Software.&lt;br &#x2F;&gt;
It was a great event as usual and I really enjoyed the talks and meeting great people!&lt;&#x2F;p&gt;
&lt;p&gt;This year I had my 4th talk at this conference, about my game 99Managers Futsal Edition.
The abstract and slides can be found on the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.sfscon.it&#x2F;talks&#x2F;making-a-sport-management-game-in-godot&#x2F;&quot;&gt;SFSCON website&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
The talk covers how the project started in 2021 and what the future plans are.
It also shows why I chose Godot, how it works and what other tools I used.
Then a basic overview of the components used in the game is shown and what parts can be reused.
The plan is to create also other sport management games, so reusable code is really important.
Finally I asked people to join the community, by improving the game and creating more FOSS games.&lt;&#x2F;p&gt;
&lt;p&gt;You can watch the registration of my talk on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;vimeo.com&#x2F;1140922391&quot;&gt;Vimeo&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;other-talks&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#other-talks&quot; aria-label=&quot;Anchor link for: other-talks&quot;&gt;Other talks&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You should check out the talks from the VLC creator
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.sfscon.it&#x2F;talks&#x2F;videolan-vlc-a-unique-story&#x2F;&quot;&gt;VideoLAN &amp;amp; VLC: a (unique) story&lt;&#x2F;a&gt;
about the funny story behind the famous orange cone video player.&lt;&#x2F;p&gt;
&lt;p&gt;Another great talk was &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.sfscon.it&#x2F;talks&#x2F;the-heart-of-our-software&#x2F;&quot;&gt;The Heart of Our Software&lt;&#x2F;a&gt;
from Karen Sandler, about why we need FOSS in critical devices, such as peacemakers.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Center buffers in Neovim</title>
          <pubDate>Wed, 15 Oct 2025 19:40:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/neovim-center-buffer/</link>
          <guid>https://simondalvai.org/blog/neovim-center-buffer/</guid>
          <description xml:base="https://simondalvai.org/blog/neovim-center-buffer/">&lt;p&gt;This time I want to share how to center a single buffer in Neovim using only Lua and no plugins.
I have not found much on this topic on the web, so I hope this helps some people!&lt;&#x2F;p&gt;
&lt;img class=&quot;image-wide&quot; src=&quot;neovim-centered-buffer.webp&quot; alt=&quot;A screenshot of Neovim with a centered buffer.&quot;&gt;
&lt;p&gt;This only works on Neovim, afaik, because Vim can&#x27;t yet modify the statuscolumn, like Neovim.&lt;&#x2F;p&gt;
&lt;p&gt;Note: I used Neovim v0.10.4 on Debian 13, while writing this blogpost.
Statuscolumn was introduced in Neovim v0.10.
This won&#x27;t work with older versions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;no-plugins-please&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#no-plugins-please&quot; aria-label=&quot;Anchor link for: no-plugins-please&quot;&gt;No plugins, please&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Before we dive into how to achieve this, I want to explain why I didn&#x27;t use plugins.
First, all plugins I found use multiple empty side windows to center the main window.
In my opinion that solution is sub-optimal, because this can interfere with my workflow.&lt;&#x2F;p&gt;
&lt;p&gt;Secondly, my personal preference is to use only plugins, I really need.
I don&#x27;t like relying on third party dependencies and I prefer using simple and stable software.
Neovim can already do a lot out of the box and if something is missing, I can add it with Lua.
That is what a hackable editor is all about.&lt;&#x2F;p&gt;
&lt;p&gt;The third reason is that I use Debian.
Debian does not distribute the latest bleeding edge software.
The goal of Debian is to create a stable and reliable operating system.
This means I don&#x27;t have the latest version of Neovim installed.
Most plugins move fast and require the latest version.
Fewer plugins mean less trouble and version incompatibilities.&lt;&#x2F;p&gt;
&lt;p&gt;If you are interested, you can find my tiny Neovim configuration &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;dotfiles&quot;&gt;on Codeberg&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-problem&quot; aria-label=&quot;Anchor link for: the-problem&quot;&gt;The problem&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When I started using Neovim, I still had a different opinion on plugins, so I used a lot of them.
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;preservim&#x2F;nerdtree&quot;&gt;NERDTree&lt;&#x2F;a&gt; was my file explorer for some months.
I always had a NERDTree buffer open on the left side, that centered the active buffer.
Just like all the &lt;em&gt;normal&lt;&#x2F;em&gt; editors and IDEs have.&lt;&#x2F;p&gt;
&lt;p&gt;But time passed and I switched NERDTree for &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;stevearc&#x2F;oil.nvim&quot;&gt;oil.nvim&lt;&#x2F;a&gt;.
Oil integrates better with the Vim workflow has no permanently open side pane.
If you need to explore the current directory, you do it in a buffer.
When you are done, the buffer disappears.
This week I even got rid of oil.nvim for the good old default Netrw.&lt;&#x2F;p&gt;
&lt;p&gt;But without a side pane, always looking left, does not feel right :-)
I guess my neck agrees with this.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-solution&quot; aria-label=&quot;Anchor link for: the-solution&quot;&gt;The solution&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I simply want to center horizontally the current window, if it is alone.
If more exists or Neovim does not occupy the whole screen, they should align to the left.
But if windows are separated vertically, they should be centered again.&lt;&#x2F;p&gt;
&lt;p&gt;The trick is adding a lot of spaces to the statuscolumn, if needed.&lt;&#x2F;p&gt;
&lt;p&gt;First you need to know the width (column count) of Neovim, while it is using the whole screen.
For that, run the following command in Neovim.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;lua&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; print&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_win_get_width&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In my case, the width is 191 columns.
This can vary depending on font and screen size.
The width is hard-coded for now and needs to be adapted manually, if needed.&lt;&#x2F;p&gt;
&lt;p&gt;By adding the following code to your init.lua file, you get the above described behavior.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; full_screen&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 191&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; default status column, simply 2 spaces&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; statuscolumn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;  &amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; status column if only one buffer is open&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; (full_screen - text width) &#x2F; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; statuscolumn_wide&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; string.rep&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;, (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;full_screen&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; statuscolumn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; set default&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;statuscolumn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; statuscolumn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; check window list count and adapt padding&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_create_autocmd&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;BufEnter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;BufWinEnter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;BufWinLeave&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;WinEnter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;WinLeave&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;WinResized&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;VimResized&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}, {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  callback&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;      local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; winwidth&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_win_get_width&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;0&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;      if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; winwidth&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;full_screen&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;statuscolumn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; statuscolumn_wide&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;      else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;o&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;statuscolumn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; statuscolumn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;      end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;  end&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note that this triggers on different events, like WinResized, BufEnter and so on.
That makes windows adapt dynamically during runtime, depending on the screen width.
If you reduce the size of the terminal, the window will act accordingly.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-fine-tuning&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#further-fine-tuning&quot; aria-label=&quot;Anchor link for: further-fine-tuning&quot;&gt;Further fine-tuning&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This setup only adds spaces to the status column, without any line number or other symbols.
You can simply add one of the following codes to the statuscolumn variable defined above.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;%&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; of&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; currently&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; drawn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;%&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	relative&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; line&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; number&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; of&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; currently&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; drawn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;%&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	sign&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; column&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; currently&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; drawn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;%&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;	fold&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; column&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; currently&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; drawn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For example this would show the line numbers.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; statuscolumn&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; %l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can also use different colors for uneven rows for example, or whatever comes to your mind.
Simply read the docs for more information on that.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt;help&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; statuscolumn&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;One final thing must be said about performance.
In the statuscolumn docs you might see a &lt;strong&gt;WARNING&lt;&#x2F;strong&gt; about statuscolumn.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;WARNING: this expression is evaluated for each screen line so defining&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;an expensive expression can negatively affect render performance.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Keep this in mind if you want to keep your Neovim fast and snappy.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>One year as full-time solo game dev</title>
          <pubDate>Tue, 16 Sep 2025 16:50:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/one-year-solodev/</link>
          <guid>https://simondalvai.org/blog/one-year-solodev/</guid>
          <description xml:base="https://simondalvai.org/blog/one-year-solodev/">&lt;p&gt;On this exact day one year ago, my journey as a solo game developer began.
Here I will share my experiences and what I learned.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-effort-estimations-were-wrong&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-effort-estimations-were-wrong&quot; aria-label=&quot;Anchor link for: my-effort-estimations-were-wrong&quot;&gt;My effort estimations were wrong&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;A year ago I thought that my game was about 60% complete, missing a few features and visual polish.
Now, a full year later, my game is about 60% complete, missing a few features and visual polish.&lt;br &#x2F;&gt;
What changed is that I saw the real work needed to really finish a bigger game.
Behind the scenes, there are so many things to do that making estimates without experience is impossible.&lt;&#x2F;p&gt;
&lt;p&gt;This wasn&#x27;t planned, of course.
My initial estimate was that it would take me 6 months to finish the game if I worked full time on it.
But now, a year later, I really don&#x27;t know when it will be finished.
The game is currently released as an open beta, to get feedback and some early players.
Now the plan is to release it to Steams Early Access, once some users say that it is great.&lt;&#x2F;p&gt;
&lt;p&gt;A great suggestion I can give is not to talk about a release date, when you are not 110% sure about it.
Estimations are always wrong and you might want to play and test the game before a full release.
So once you have a complete, nice looking game with feedback, you can start to think about a date.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;time-tracking-to-stay-motivated&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#time-tracking-to-stay-motivated&quot; aria-label=&quot;Anchor link for: time-tracking-to-stay-motivated&quot;&gt;Time tracking to stay motivated&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Simply track the time you work on something during the day.
This is something that made the biggest difference for me.
It gives you an overview on &lt;strong&gt;how long&lt;&#x2F;strong&gt; you worked on something.&lt;&#x2F;p&gt;
&lt;p&gt;So at the end of the day I can rest with peace in my mind, if I worked 8 hours.
It also motivates me to work more the next day, if I missed some hours the day before.&lt;&#x2F;p&gt;
&lt;p&gt;I normally just write the project tag I&#x27;m working and a short description.
First I used the Thunderbird calendar, but recently switched to a simple text file.
This makes it easier to run scripts on it for statistics (something I haven&#x27;t done yet),
and a text file always works, no matter what.&lt;&#x2F;p&gt;
&lt;p&gt;Here an example for typical day with entries consisting of
&lt;code&gt;+ project-tag description&lt;&#x2F;code&gt; with start time above and end below.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;markdown&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);font-weight: bold;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);font-weight: bold;&quot;&gt; 28.08 thu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 07:30&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 99 team logos&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 12:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 13:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 99 team logos&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 16:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 99 new gameplay video&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 17:30&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 18:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 99 new gameplay video&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 19:30&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 21:00&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;+&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; co upgrade to godot 4.4 and add keyboard support&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; 23:30&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you can see I don&#x27;t get too much in detail and don&#x27;t write every feature.
The minimum time period I track is 30 minutes.&lt;br &#x2F;&gt;
This works well for me but might not for you.
Just start tracking your time and see if it helps you or not.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;never-giving-up&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#never-giving-up&quot; aria-label=&quot;Anchor link for: never-giving-up&quot;&gt;Never giving up&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is really important when creating time intensive projects, like games.
As exciting it might sound to work on your game all day and every day, the magic fades quite quickly.
There are highs and lows and keeping working on something that seems unreachable, can be difficult.&lt;&#x2F;p&gt;
&lt;p&gt;But by never giving up I will finish this game one day and be really proud of myself.
Sometimes I look on old screenshots of the game to see the progress I have made.
This helps a lot, especially when doubts are haunting me.&lt;&#x2F;p&gt;
&lt;p&gt;Starting and finishing a project can also be a good showoff for future job applications.
And HR departments love to see resilience and motivation.
So even if my game is a financial flop, it could lead to better jobs in the future.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;10k-hours&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#10k-hours&quot; aria-label=&quot;Anchor link for: 10k-hours&quot;&gt;10k hours&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There is a saying that if you spend ten thousand hours doing something, you get really good at it.
This year I spent around two to three thousands of hours working on the game.
So I&#x27;m still not really good at it.
But If I look at my older games, or even the very first game, the improvement is huge.&lt;&#x2F;p&gt;
&lt;p&gt;So even if my games are still not really great and miss the masters touch, I&#x27;m getting closer and
closer to this ten thousand hours.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;taking-breaks&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#taking-breaks&quot; aria-label=&quot;Anchor link for: taking-breaks&quot;&gt;Taking breaks&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I had a git commit streak of &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@dulvui&#x2F;114437065612740690&quot;&gt;687 days&lt;&#x2F;a&gt;
with at least one commit on the game per day.&lt;br &#x2F;&gt;
This helped me a lot to keep working on the game while having a full time job.
I would add some new features or just fix a typo to keep the streak.
But most important, I didn&#x27;t stop working on the game.&lt;&#x2F;p&gt;
&lt;p&gt;Before this streak I would maybe work 2 months on the game, and take a 2 week break.
With this approach it was really difficult to stay motivated.
And even harder to remember what I was working on.
So the streak helped to sit at least once a day in front of the computer, open the game and see.&lt;&#x2F;p&gt;
&lt;p&gt;But once I went all in and quit my job one year ago, it was simply too much.
I got tired and had low motivation to work on it every day.&lt;&#x2F;p&gt;
&lt;p&gt;Taking my mind off the game is in my opinion a healthy thing to do,
especially since I work on it for about 8 hours or more a day.
Now I no longer work on weekends, except if I really want to or there is something exciting to do.
My motivation is again on it&#x27;s best and I have more time to enjoy other things.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;respect-for-my-work&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#respect-for-my-work&quot; aria-label=&quot;Anchor link for: respect-for-my-work&quot;&gt;Respect for my work&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Since I started this journey, only a few people really respect and understand my work.
Most people say I don&#x27;t have a job and don&#x27;t even really work.
And of course because I&#x27;m just working on some games, that can&#x27;t be serious.&lt;&#x2F;p&gt;
&lt;p&gt;I learned to ignore this and just keep going to follow my plan.
I really like working from home and doing what I really like to do,
(nearly) without any external input and using only my ideas.&lt;&#x2F;p&gt;
&lt;p&gt;There is no Sunday I think &quot;Oh no, tomorrow I have to work again&quot;.
Actually the exact opposite is the case, that most of the times I&#x27;m exited to get back to work.
The same happens if I&#x27;m on vacations.&lt;&#x2F;p&gt;
&lt;p&gt;So my final advice here is follow your dreams, if you are in a privileged position to do so.
If you really like something and it can possibly generate some income, go for it.
And listen to friends and family, but keep your ideas and stick with your plan, no matter what.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;i-don-t-like-playing-my-games-yet&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#i-don-t-like-playing-my-games-yet&quot; aria-label=&quot;Anchor link for: i-don-t-like-playing-my-games-yet&quot;&gt;I don&#x27;t like playing my games (yet?)&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One curious thing I have experienced so far is that I don&#x27;t really play my games.
I would have never said that this would happen, before starting developing games.
So it amazes me even more, when I see people playing for hours my game and completing everything.&lt;&#x2F;p&gt;
&lt;p&gt;The game I&#x27;m currently working on was actually the first game I thought this would be cool to play.
But I still didn&#x27;t play it more than the time needed to test it.&lt;&#x2F;p&gt;
&lt;p&gt;I personally think there could be three reasons for this&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;When you create a game and know how it works, it looses the &quot;magic touch&quot; of the unexpected.
I know nearly everything about the game, except the bugs and so I don&#x27;t need really to learn and improve.&lt;&#x2F;li&gt;
&lt;li&gt;It&#x27;s really difficult to enjoy my games, because I see all the things that can be improved or fixed.&lt;&#x2F;li&gt;
&lt;li&gt;I still haven&#x27;t made a really good game.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;Only time will tell if I will enjoy playing my games one day.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;ignore-the-noise&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ignore-the-noise&quot; aria-label=&quot;Anchor link for: ignore-the-noise&quot;&gt;Ignore the noise&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As many aspiring solo developers, I checked out social media like Reddit for advice and experience
of fellow developers.
This can be a great resource for learning how to create a successful game.&lt;&#x2F;p&gt;
&lt;p&gt;But it can also be really demotivating to see other games getting thousands of whishlists on Steam,
while my game got around 400 as of today.
If I wouldn&#x27;t have seen this on Reddit, I would be the happiest person on earth, knowing that
FOUR HUNDRED people saw my game and thought &quot;this looks nice, I might play it when it&#x27;s released&quot;.&lt;&#x2F;p&gt;
&lt;p&gt;So I learned to ignore the noise and focus on my game.
I still check social media and other platforms to read about game development.
But I try to look at it from a different angle, by thinking about how my game could reach this numbers.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;marketing-or-not-to-marketing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#marketing-or-not-to-marketing&quot; aria-label=&quot;Anchor link for: marketing-or-not-to-marketing&quot;&gt;Marketing, or not to marketing&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I watched videos, read articles and whatever I accidentally found.
And most of the times the first question is: what is your budget?
My current budget is zero.&lt;&#x2F;p&gt;
&lt;p&gt;So I created accounts on the socials I use, Mastodon, Bluesky and Matrix.
And some I thought might be attracting players such as Discord, Reddit and YouTube.
Currently Discord is the one that worked the best for me, with 32 players in my server.
Not huge numbers, I know, but for me it&#x27;s a great starting point to learn and improve.&lt;&#x2F;p&gt;
&lt;p&gt;My absolute favorite marketing method is this blog post.
I really like it to write and express my thoughts and ideas.
I don&#x27;t have tracking, so my only statistics are server access logs and the Google Search console.
I currently get around 20 clicks per day, according to Google and that&#x27;s great!
Maybe one day like to create videos I will create YouTube videos, but for now writing works just fine.
Finding something you like to do and using it to get visibility is the best marketing in my opinion.&lt;&#x2F;p&gt;
&lt;p&gt;I also printed some stickers, I normally distribute after talks or at events.
Note to this: high quality stickers can cost quite a lot, like +100€ for a few stickers.
A cheap alternative can be to buy adhesive A4 paper and use a common printer.
I got 10 adhesive pages for 5€ and created about 50 stickers with one page.&lt;&#x2F;p&gt;
&lt;p&gt;I think it also highly depends on the type of a game, if intensive marketing is needed.
If there are many competitors, marketing might be the only way to attract users.
In my case there is currently only one other Futsal Manager available on Steam.
Picking a niche market can reduce the need for marketing a lot, at least that&#x27;s my theory.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;done-is-better-than-perfect&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#done-is-better-than-perfect&quot; aria-label=&quot;Anchor link for: done-is-better-than-perfect&quot;&gt;Done is better than perfect&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is one of the most important advice I can give.
It might also be one of the most difficult to learn and I&#x27;m still failing at it badly sometimes.&lt;&#x2F;p&gt;
&lt;p&gt;It happened so many times that I got stuck somewhere, because I was seeking perfection.
That let me into an endless loop of refactoring and re-implementing functionality, like the match engine.
Slowly I learned to see that something is good enough, for now.
Then I would start working on something else and forget about it.
Coming back to it after some days or even weeks clears my mind and lets me see the problem from a
different angle.&lt;&#x2F;p&gt;
&lt;p&gt;Now I work in this loop, where I get something done (good enough) and iterate over it again after
some time passed.
This prevents the frustrating situation of feeling stuck in the never perfect state.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;notes-and-plans&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#notes-and-plans&quot; aria-label=&quot;Anchor link for: notes-and-plans&quot;&gt;Notes and plans&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I tried a lot of things like Kanbans with todo, doing, done lanes or creating issues on Codeberg.
I also had multiple note books and files with all ideas, bugs and features scattered around.&lt;&#x2F;p&gt;
&lt;p&gt;For now I ended up with a single todo.md file accessible from phone and computer.
The I have one notebook for offline notes, handy for when I have ideas while playing other games.
And some paper lying around my desk for fire and forget notes.&lt;&#x2F;p&gt;
&lt;p&gt;I simply write ideas, bugs and missing features down until they are resolved.
I also don&#x27;t plan much in the future and decide in the moment what to do.
This works pretty well for me and I really like this spontaneous approach.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;naming-things-is-difficult&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#naming-things-is-difficult&quot; aria-label=&quot;Anchor link for: naming-things-is-difficult&quot;&gt;Naming things is difficult&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I spend a LOT of time finding a fitting name for my game and game studio.
Immediately the famous naming joke came to my mind.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;There are only two hard things in Computer Science: cache invalidation and naming things.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-- Phil Karlton&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I collected long lists with potential names.
Short, long, without any meaning, I really had a lot of names.
This distilled down to a few names, after hours of seeking the perfect name.&lt;&#x2F;p&gt;
&lt;p&gt;In the end I took 99Managers for the game following these main ideas&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;is unique&lt;&#x2F;li&gt;
&lt;li&gt;easy to remember&lt;&#x2F;li&gt;
&lt;li&gt;.com and .org domains available&lt;&#x2F;li&gt;
&lt;li&gt;word trademark registration possible&lt;&#x2F;li&gt;
&lt;li&gt;can be used as umbrella name for different sport editions&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Finding names can be really hard, at least for me.
I could waste days finding new names, while searching if the domain is available.
But I really need to keep in mind that the thing that really matters is &lt;strong&gt;making a fun game&lt;&#x2F;strong&gt;.
A good name might be easier to remember or attract some users, but finally the game is what matters.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-a-trademark&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#getting-a-trademark&quot; aria-label=&quot;Anchor link for: getting-a-trademark&quot;&gt;Getting a trademark&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So after I decided on the name, I registered a word trademark for 99MANAGERS in the category
of video games in the European Union.
This was quite expensive, because the registration fee alone is 850€.
The idea is to use this name also as umbrella name for other editions, as mentioned before.
So for example if one day I create 99Managers Volleyball Edition, the name 99Managers would still be
protected in the European Union.&lt;&#x2F;p&gt;
&lt;p&gt;The main reason for this is that the game is Open Source, so I wanted to protect at least the name.
Everybody can still create and distribute their own version of the game, but the name has to be
changed.&lt;&#x2F;p&gt;
&lt;p&gt;Another reason is that again, I spent too much time on Reddit, reading about trademarks.
But in the end some advice I read there might be true: it&#x27;s good to have it, &lt;strong&gt;before&lt;&#x2F;strong&gt; you need it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;finances&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#finances&quot; aria-label=&quot;Anchor link for: finances&quot;&gt;Finances&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I&#x27;m currently living on my savings and I hope to finish the game soon, to see if I can generate
some income.&lt;&#x2F;p&gt;
&lt;p&gt;Many ask how I&#x27;m able to stay without a job for such a long period.
Normally I would say that I don&#x27;t spend much, eat a lot at home and &lt;strong&gt;don&#x27;t own a car&lt;&#x2F;strong&gt;.
I also buy a lot of used things and recently started selling stuff I no longer need.&lt;&#x2F;p&gt;
&lt;p&gt;Self funding is what currently works for me and it makes me completely independent and free.
There are also other ways to finance a game, like getting investors, working with  publishers or
crowdfunding.
For now I have chosen the self-finance way, but maybe someday this will change.
Crowdfunding sounds interesting to me, because I could stay independent.
I also often see &quot;Co-financed by culture fund of PUT_COUNTRY_HERE&quot; in some games I played.
A lot of countries support cultural works, like video games, with financial support
This might be another way to get funding, while staying independent.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;focus-on-the-game&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#focus-on-the-game&quot; aria-label=&quot;Anchor link for: focus-on-the-game&quot;&gt;Focus on the game&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;With all the stuff to do as a solo game developer, I sometimes forget to focus on the game.
The game is what really matters.
It is the base for real success.
You can have the best marketing, but without a fun game, that doesn&#x27;t really matter.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t have the numbers on how much of my time I spend on the game and how much on the rest.
But I would guess it is about 80&#x2F;20.
That works for me and I recently shifted again more focus on the game.&lt;&#x2F;p&gt;
&lt;p&gt;Now overall, I care less about naming things, social media presence and related things.
Because I know and also see it in real life, that successful games, are great games. Period.
Nothing else really matters.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;plan-a-b-c-y-and-z&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#plan-a-b-c-y-and-z&quot; aria-label=&quot;Anchor link for: plan-a-b-c-y-and-z&quot;&gt;Plan A, B, C, Y and Z&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;My plan A is finishing the game and making a living as a independent FOSS game developer.
If this plan fails (the chances of failure are about 99%), I still have some backup plans.
Most of my backup plans should allow me to keep working partially on my games.&lt;&#x2F;p&gt;
&lt;p&gt;I have a plan B, that is taking freelance work for a few hours a week to keep living costs covered.
And a plan C, that is taking a part time job, if plan B fails.&lt;&#x2F;p&gt;
&lt;p&gt;The following plans are named with the last letters in the alphabet, because they are my last resort.
Hopefully if plan B and C fail, time comes up with a plan D, E and F.&lt;br &#x2F;&gt;
But anyways, my plan Y is getting a full time job as a game developer.
That could even be a good plan, to see how real professionals work.
Finally plan Z, that is my final plan I really hope not having to execute,
is going back to a full time job as a normal software developer.&lt;&#x2F;p&gt;
&lt;p&gt;I guess that I will switch to Plan B soon, to don&#x27;t consume my whole savings and create different
sources of income.
Even if my game would sell well, it doesn&#x27;t mean that it will still sell in a month or in a year.
The same counts for future games, that could be hits or complete failures.
Having alternatives is always recommended and can also create other opportunities.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;that-s-all-folks&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#that-s-all-folks&quot; aria-label=&quot;Anchor link for: that-s-all-folks&quot;&gt;That&#x27;s all folks&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I guess with this I just wrote my longest &quot;only text, no code&quot; blog post so far, but this memorable
event was worth it.
Thank you for reading and see you in a year again, for another one!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Godot code style, project structure and friends</title>
          <pubDate>Sun, 17 Aug 2025 20:05:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-best-practices/</link>
          <guid>https://simondalvai.org/blog/godot-best-practices/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-best-practices/">&lt;p&gt;I started using Godot 3 around 5 years ago.
A lot of things changed since then.
Godot 4 and GDScript 2.0 are out and I learned a lot about writing better code.&lt;&#x2F;p&gt;
&lt;p&gt;Everything here is covered in the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;&quot;&gt;official Godot docs&lt;&#x2F;a&gt;
and that is the best place to get the correct and up to date information.
Said that, I just will point you to the right place in the docs and add my two cents.&lt;&#x2F;p&gt;
&lt;p&gt;Note: Godot version 4.4.1 is used here, some things might be different in other versions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;write-good-code&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#write-good-code&quot; aria-label=&quot;Anchor link for: write-good-code&quot;&gt;Write good code&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Everybody can has his own thoughts about what defines good code.
But I think we can all agree that &lt;strong&gt;maintainability&lt;&#x2F;strong&gt;, &lt;strong&gt;readability&lt;&#x2F;strong&gt; and &lt;strong&gt;organization&lt;&#x2F;strong&gt; are king.
This increase the developer experience and can increase the time of your coding sessions.&lt;&#x2F;p&gt;
&lt;p&gt;Another important key aspect might be &lt;strong&gt;performance&lt;&#x2F;strong&gt;, but only after the code works and looks good.
And never forget &lt;strong&gt;done is better than perfect&lt;&#x2F;strong&gt;.
Endless code style adjustments and refactoring can stop progress.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;project-organization&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#project-organization&quot; aria-label=&quot;Anchor link for: project-organization&quot;&gt;Project organization&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There is a dedicated page in the docs for
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;best_practices&#x2F;project_organization.html&quot;&gt;project organization&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The main takeaway is to create a &lt;strong&gt;directory for every scene&lt;&#x2F;strong&gt; and put all scripts, assets and scene
files there.&lt;&#x2F;p&gt;
&lt;p&gt;I do it a bit different, since most of my games don&#x27;t have many assets and I also keep track of
used licenses for third party assets.
So having all assets in a single directory makes it easier to keep track of used third party assets.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&#x2F;&lt;&#x2F;strong&gt; Godot unrelated files, like README.md or LICENSE&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&#x2F;game&#x2F;&lt;&#x2F;strong&gt; godot project root&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&#x2F;game&#x2F;src&#x2F;&lt;&#x2F;strong&gt; scripts and scenes&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&#x2F;game&#x2F;src&#x2F;const.gd&lt;&#x2F;strong&gt; global constants&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&#x2F;game&#x2F;src&#x2F;global.gd&lt;&#x2F;strong&gt; global singleton&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&#x2F;game&#x2F;assets&#x2F;&lt;&#x2F;strong&gt; assets, including audio and fonts&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&#x2F;game&#x2F;themes&#x2F;&lt;&#x2F;strong&gt; theme files and related files, like style resources&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&#x2F;game&#x2F;translations&#x2F;&lt;&#x2F;strong&gt; csv or po&#x2F;pot translation files&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;&#x2F;game&#x2F;script_templates&#x2F;&lt;&#x2F;strong&gt; custom &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;scripting&#x2F;creating_script_templates.html&quot;&gt;script templates&lt;&#x2F;a&gt;
including license headers and more&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This structure crystallized for me over time, but might not work for you.
Time will show what is best for you and your projects.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;code-style&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#code-style&quot; aria-label=&quot;Anchor link for: code-style&quot;&gt;Code style&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;latest&#x2F;tutorials&#x2F;scripting&#x2F;gdscript&#x2F;gdscript_styleguide.html&quot;&gt;code style&lt;&#x2F;a&gt;
the documentation is much more detailed.&lt;&#x2F;p&gt;
&lt;p&gt;I regret not having read this earlier.
My first two Godot projects have a horrible code style.
But as many times in life, errors are the best teachers.
Now I really care about how my code is written and structured.
I prefer now to fix things immediately instead of waiting.&lt;&#x2F;p&gt;
&lt;p&gt;I respect now rigidly the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;latest&#x2F;tutorials&#x2F;scripting&#x2F;gdscript&#x2F;gdscript_styleguide.html#code-order&quot;&gt;code order&lt;&#x2F;a&gt;
and made also a bash alias that prints me the order, for easy access.
I saw people on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;godot&#x2F;comments&#x2F;1mmrozm&#x2F;hung_directly_over_my_pc_so_ill_never_have_to&#x2F;&quot;&gt;reddit&lt;&#x2F;a&gt;
printing the code order docs and framing it above the monitors on the wall.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;naming-conventions&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#naming-conventions&quot; aria-label=&quot;Anchor link for: naming-conventions&quot;&gt;Naming conventions&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Also here I didn&#x27;t follow the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;latest&#x2F;tutorials&#x2F;scripting&#x2F;gdscript&#x2F;gdscript_styleguide.html#naming-conventions&quot;&gt;official convention&lt;&#x2F;a&gt;
for years.
Then I had to rename hundreds of files and always follow now the way it should be.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;static-typing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#static-typing&quot; aria-label=&quot;Anchor link for: static-typing&quot;&gt;Static typing&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Coming from Java with static types I really miss the rigid type checks at compile time.
I really recommend using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;4.4&#x2F;tutorials&#x2F;scripting&#x2F;gdscript&#x2F;static_typing.html&quot;&gt;static typing&lt;&#x2F;a&gt;
in Godot, for less bugs, better error detection and performance.
It also allows to find errors fast, as described in a previous &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;godot-runtime-errors&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;The docs state that best practice is to always use it or never.
Mixing static and dynamic typing is seen as bad practice and can cause confusion.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;scene-unique-nodes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#scene-unique-nodes&quot; aria-label=&quot;Anchor link for: scene-unique-nodes&quot;&gt;Scene unique nodes&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is a nice way to keep mental sanity while accessing Nodes in code.
I used to drag and drop Nodes into the script editor, while holding Ctrl, to get the full node path.
But since I switched to Neovim as my main editor, I cannot do that anymore.&lt;&#x2F;p&gt;
&lt;p&gt;Better, because now I use the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;scripting&#x2F;scene_unique_nodes.html&quot;&gt;Scene unique nodes&lt;&#x2F;a&gt;
that allow accessing nodes without writing the full path.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# access by unique name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var label: Label = %Label&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# instead of full path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var label: Label = $MarginContainer&#x2F;VBoxContainer&#x2F;YetAnotherContainer&#x2F;Label&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is so much cleaner in the code and most important Nodes can be &lt;strong&gt;moved and renamed&lt;&#x2F;strong&gt; freely in
the scene tree, without breaking the path in the code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;uids&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#uids&quot; aria-label=&quot;Anchor link for: uids&quot;&gt;UIDs&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Since Godot 4.4 added &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;godotengine.org&#x2F;article&#x2F;uid-changes-coming-to-godot-4-4&#x2F;&quot;&gt;UID support&lt;&#x2F;a&gt;
it is possible to do access script files with their unique UID, instead of the full file path.
This brings a similar logic, as we have with unique node names, to script and scene files.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# access by UID&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var scene: PackedScene = load(&amp;quot;uid:&#x2F;&#x2F;b48hr5ervcv&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# instead of full path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var scene: PackedScene = load(&amp;quot;res:&#x2F;&#x2F;src&#x2F;screens&#x2F;settings&#x2F;audio&#x2F;audio_settings.gd&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With this also files can be &lt;strong&gt;moved and renamed&lt;&#x2F;strong&gt; freely, without breaking paths in the code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;linters-and-formatters&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#linters-and-formatters&quot; aria-label=&quot;Anchor link for: linters-and-formatters&quot;&gt;Linters and formatters&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Scony&#x2F;godot-gdscript-toolkit&#x2F;&quot;&gt;gdtoolkit&lt;&#x2F;a&gt; is a python tool that provides
a parser, linter, formatter and code metrics calculator.
I have to admit that I tried the linter and formatter and I didn&#x27;t like it.
At the time, the false positives were simply too many.&lt;br &#x2F;&gt;
If years of JS linters at work taught me one thing, it is that they never work properly ;-)
But I will checkout the tool every few months and see if it improved and you should too.
Maybe for you it works!&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>My new workstation - HP Pro Tower 400 G9</title>
          <pubDate>Thu, 17 Jul 2025 09:49:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/new-tower-pc/</link>
          <guid>https://simondalvai.org/blog/new-tower-pc/</guid>
          <description xml:base="https://simondalvai.org/blog/new-tower-pc/">&lt;p&gt;I have been working on a Thinkpad T470s for about 2 years now.
It has 20GB RAM, a 1TB SSD and an i5-7200U with 2 cores and 4 threads.
I really love it and using the old mechanical docking stations is a true pleasure.
I got it for 120€ from the company I used to work for.
Now I will probably use it only when I leave my house or want to work from my sofa.&lt;&#x2F;p&gt;
&lt;p&gt;Yesterday I bought a used HP Pro Tower 400 G9 model 6A773EA from a local online market place.
It has a i7-12700 with &lt;strong&gt;12 cores&lt;&#x2F;strong&gt; and &lt;strong&gt;20 threads&lt;&#x2F;strong&gt;, 32GB RAM and a 500GB SSD.
This is a true power machine compared to the laptop.
I also really like the smaller case, which is between a Small Form Factor and a regular tower.
The price was just &lt;strong&gt;380€&lt;&#x2F;strong&gt;, a real steal in my opinion, because new it costs around 1000€.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-not-make-a-custom-build&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-not-make-a-custom-build&quot; aria-label=&quot;Anchor link for: why-not-make-a-custom-build&quot;&gt;Why not make a custom build&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I really like the idea of building my own PC someday.
I&#x27;m also not a big fan of HP, Dell or similar brands.
But this time I decided to get this pre-built device for three main reasons&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;It was cheap&lt;&#x2F;li&gt;
&lt;li&gt;It works out of the box (at least I hoped)&lt;&#x2F;li&gt;
&lt;li&gt;I would get lost in details when making a custom built PC&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;p&gt;This should save me time and money to actually get things done :-)&lt;&#x2F;p&gt;
&lt;p&gt;As you can see, I like to get &lt;strong&gt;used&lt;&#x2F;strong&gt; devices for a fraction of the price.
It&#x27;s good for your wallet, for the environment and &lt;em&gt;older&lt;&#x2F;em&gt; devices normally work better with Linux.
Anyway, this tower PC is not really old, since it was released around August 2023.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;surprise-surprise&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#surprise-surprise&quot; aria-label=&quot;Anchor link for: surprise-surprise&quot;&gt;Surprise surprise&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When I first booted the device, still with Windows on it, I heard the login sound.
At first I didn&#x27;t think about it, but then It got me, how the heck can this play audio?
I never saw before that a tower PC can play audio out of the box and this one does.
It&#x27;s not a great speaker and since I have it under my desk, it doesn&#x27;t make things any better.
But always better than nothing!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;install-debian-12&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#install-debian-12&quot; aria-label=&quot;Anchor link for: install-debian-12&quot;&gt;Install Debian 12&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The first thing on my todo-list was getting rid of Windows.
My preferred OS is still Debian, starting from a installation without any desktop environment.
Then starting from a pure command line interface, I build the exact system I want.&lt;&#x2F;p&gt;
&lt;p&gt;This was the first time I tested my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;dotfiles&quot;&gt;install script&lt;&#x2F;a&gt;
on a complete new machine.
And guess what, it didn&#x27;t work.
CLASSIC.
So I had to do some manual fixes and take notes on what was missing or went wrong.
Hopefully next time this will work better.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;get-wifi-to-work&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#get-wifi-to-work&quot; aria-label=&quot;Anchor link for: get-wifi-to-work&quot;&gt;Get WiFi to work&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Debian 12 was initially released just a few months before this PC came out.
So I faced some issues, when installing it, because the WiFi card was not supported out of the box.
It has a &lt;strong&gt;Realtek RTL8852BE&lt;&#x2F;strong&gt;, with WiFi 6 and Bluetooth.
This card is supported from the Linux Kernel &amp;gt;6.2 and Debian 12 uses 6.1.&lt;&#x2F;p&gt;
&lt;p&gt;After some troubleshooting to get the card running, I finally got it to work.
The trick was getting a newer Linux kernel from bookworm-backports.
First, you have to add bookworm-backports to your apt &lt;strong&gt;&#x2F;etc&#x2F;apt&#x2F;sources.list&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; add backports for kernel &amp;gt;6.2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;deb&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; bookworm-backports&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; non-free-firmware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;deb&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; bookworm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; non-free-firmware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;deb-src&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; bookworm&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; non-free-firmware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;deb&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; http:&#x2F;&#x2F;security.debian.org&#x2F;debian-security&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; bookworm-security&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; non-free-firmware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;deb-src&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; http:&#x2F;&#x2F;security.debian.org&#x2F;debian-security&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; bookworm-security&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; non-free-firmware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; bookworm-updates, to get updates before a point release is made;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; see https:&#x2F;&#x2F;www.debian.org&#x2F;doc&#x2F;manuals&#x2F;debian-reference&#x2F;ch02.en.html#_updates_and_backports&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;deb&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; bookworm-updates&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; non-free-firmware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;deb-src&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; http:&#x2F;&#x2F;deb.debian.org&#x2F;debian&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; bookworm-updates&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; main&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; non-free-firmware&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After that I could get a newer kernel from backports.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; update&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; bookworm-backports&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; linux-image-amd64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Backports packages are, of course, &lt;strong&gt;not tested&lt;&#x2F;strong&gt; in detail like the default stable packages.
So only strictly necessary packages should be installed from there.
The good thing is that with this I should be able to seamlessly upgrade to Debian 13.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;dulvui@rook:~$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; uname&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;a&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Linux&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; rook&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; 6.12.32+bpo-amd64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;1 SMP PREEMPT_DYNAMIC Debian 6.12.32-1~bpo12+1 (2025-06-21) x86_64 GNU&#x2F;Linux&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Finally I installed the firmware-realtek package and everything worked after reboot.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; firmware-realtek&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This actually took me some hours, trying to install the driver manually or upgrading to Debian 13.
But using backports on a fresh Debian 12 install is easy and creates the most stable system possible.&lt;&#x2F;p&gt;
&lt;p&gt;I have to admit that this was the first time I considered using Fedora or Arch.
But finally Debian worked also this time and I learned some new cool tricks with backports.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-real-impact&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-real-impact&quot; aria-label=&quot;Anchor link for: the-real-impact&quot;&gt;The real impact&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;By comparing CPU benchmarks I expected that this new PC should be &lt;strong&gt;many times faster&lt;&#x2F;strong&gt; than my laptop.
It feels &lt;strong&gt;snappier&lt;&#x2F;strong&gt; and generally faster, but not as much as benchmarks suggested.
I guess this is related to the fact that most software still doesn&#x27;t use multi-threading.&lt;&#x2F;p&gt;
&lt;p&gt;My game also does &lt;strong&gt;not support multi-threading&lt;&#x2F;strong&gt; yet.
So it runs faster here, but not to a magnitude teased by the benchmarks.
I expected that the match simulation would be much faster, but I was wrong.
Everything runs on one core anyway, so it doesn&#x27;t make much difference.
Now I have no excuse to skip learning how to use threads properly in Godot.&lt;&#x2F;p&gt;
&lt;p&gt;Another thing to consider is that my setup is quite &lt;strong&gt;lightweight&lt;&#x2F;strong&gt;.
I use sway-wm, code mainly with the Godot engine and use Neovim as my editor.
This combination already felt fast and snappy on my laptop.&lt;&#x2F;p&gt;
&lt;p&gt;I still have to try gaming on this machine.
I guess I will be really happy, once I rewrite some of the performance critical code to C&#x2F;C++.
Faster compile times and feedback should make it a more pleasant developer experience.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Unexpected orphan Nodes in Godot</title>
          <pubDate>Wed, 18 Jun 2025 20:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-orphan-nodes/</link>
          <guid>https://simondalvai.org/blog/godot-orphan-nodes/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-orphan-nodes/">&lt;p&gt;The more I work with Godot all day, the more edge cases I face.
Recently I found out that my game had orphan Nodes that can cause &lt;strong&gt;memory leaks&lt;&#x2F;strong&gt;.
It was not a huge deal, but still with some easy tricks, I could have noticed this much earlier.&lt;&#x2F;p&gt;
&lt;p&gt;Note: Godot version 4.4.1 is used here, some things might be different in other versions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;find-orphan-nodes&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#find-orphan-nodes&quot; aria-label=&quot;Anchor link for: find-orphan-nodes&quot;&gt;Find orphan nodes&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Godot has already an awesome and easy way to detect orphan Nodes.
You can see the amount over time by enabling the check-box at Debug &amp;gt; Monitors &amp;gt; Object &amp;gt; Orphan Nodes.
Or you can simply call
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;classes&#x2F;class_node.html#class-node-method-print-orphan-nodes&quot;&gt;print_orphan_nodes&lt;&#x2F;a&gt;
in your scripts at some point and it will print them into the console, if some exist.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _ready() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    print_orphan_nodes()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You will see an id, Node type and path of your orphan Nodes.
If nothing gets printed, you are fine!&lt;br &#x2F;&gt;
Here is an example with an orphan BoxContainer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;142639892262 - Stray Node: @BoxContainer@6 (Type: BoxContainer)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Normally you probably removed a Node from the tree without freeing it with &lt;strong&gt;queue_free&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;one-simple-mistake-is-enough&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#one-simple-mistake-is-enough&quot; aria-label=&quot;Anchor link for: one-simple-mistake-is-enough&quot;&gt;One simple mistake is enough&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;In my case something else happened and I just got this cryptic prints to the console.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;122456901315 - Stray Node:  (Type: Node)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;122591119050 - Stray Node:  (Type: Node)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;130929395586 - Stray Node:  (Type: Node)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There is no real information that could lead me to the problematic Node.
But after some debugging I detected that my DataUtil, that loads and saves data is the issue.&lt;&#x2F;p&gt;
&lt;p&gt;Everywhere I created a DataUtil instance, an orphan Node would appear after changing scenes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var data_util: DataUtil = DataUtil.new()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;But why?? This looks good to me.&lt;&#x2F;p&gt;
&lt;p&gt;After some more detective work, I found out that the problem was so simple, yet &lt;strong&gt;so evil&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name DataUtil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Node # JUST THIS LINE&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;By simply removing the line &lt;strong&gt;extends Node&lt;&#x2F;strong&gt;, the issue vanished.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;strong&gt;extends Node&lt;&#x2F;strong&gt; makes the DataUtil a Node, of course.
And because the Node is created, but not added to the tree, it will result as an orphan Node.&lt;&#x2F;p&gt;
&lt;p&gt;Nodes need to be released manually if not attached to a scene.
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;classes&#x2F;class_refcounted.html&quot;&gt;RefCounted&lt;&#x2F;a&gt;
objects instead get their memory released automatically if no longer used.&lt;&#x2F;p&gt;
&lt;p&gt;Now my DataUtil extends RefCounted, the default class in Godot.
This can be proved by simply creating an instance and calling &lt;strong&gt;get_class&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name NoExtends&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _init() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    print(get_class()) # prints RefCounted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Anyway it&#x27;s good practice to add the explicit &lt;strong&gt;extends RefCounted&lt;&#x2F;strong&gt; anyway.
So anybody can see what class it extends without having to know what the default is.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name WithExtends&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends RefCounted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _init() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    print(get_class()) # still prints RefCounted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I have to say that this DataUtil was once an auto-loaded Singleton.
For that reason it extended Node in the first place.
When converting it to a local instance, I forgot to remove the extends Node.
But I didn&#x27;t expect that this simple mistake could cause memory leaks.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;keep-orphan-nodes-away&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#keep-orphan-nodes-away&quot; aria-label=&quot;Anchor link for: keep-orphan-nodes-away&quot;&gt;Keep orphan Nodes away&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I will now keep the &lt;strong&gt;print_orphan_nodes&lt;&#x2F;strong&gt; call in my (custom) change scene method.
This should prevent future mistakes and let me detect them much earlier.
It&#x27;s always good to know how to detect potentially critical issues with a few simple tricks.&lt;&#x2F;p&gt;
&lt;p&gt;Last but not least a precious Godot docs entry titled:
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;best_practices&#x2F;node_alternatives.html&quot;&gt;When and how to avoid using nodes for everything.&lt;&#x2F;a&gt;
This should clear some doubts about when to use Nodes and when to use something else.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Find more errors in Godot, with a script</title>
          <pubDate>Thu, 15 May 2025 16:10:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-runtime-errors/</link>
          <guid>https://simondalvai.org/blog/godot-runtime-errors/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-runtime-errors/">&lt;p&gt;I learned programming with Java, a statically typed language.
For that reason, I really miss &lt;strong&gt;errors at compile time&lt;&#x2F;strong&gt;, when programming with GDScript in Godot.
GDScript is a dynamically typed language, that makes error detection at compile time nearly impossible.&lt;&#x2F;p&gt;
&lt;p&gt;There are many ways to make GDScript &lt;strong&gt;more strict&lt;&#x2F;strong&gt;, like adding type hints and making it
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;scripting&#x2F;gdscript&#x2F;static_typing.html&quot;&gt;statically typed&lt;&#x2F;a&gt;.
Additionally, treating more &lt;strong&gt;warnings as errors&lt;&#x2F;strong&gt; in its
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;scripting&#x2F;gdscript&#x2F;warning_system.html#doc-gdscript-warning-system&quot;&gt;warning system&lt;&#x2F;a&gt;,
will also have a positive effect on the amount of errors you will get.&lt;&#x2F;p&gt;
&lt;p&gt;Anyways, some errors will only pop up, when you &lt;strong&gt;execute&lt;&#x2F;strong&gt; the script file &lt;strong&gt;that has the error&lt;&#x2F;strong&gt;.
Just change the name of a variable or a method and forget to update all references.
&lt;strong&gt;BOOM&lt;&#x2F;strong&gt;, your game will crash when the previous name get&#x27;s accessed.
And in the worst case, this happens to the final user.&lt;&#x2F;p&gt;
&lt;p&gt;Note: Godot version 4.4.1 is used here, some things might be different in other versions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;yet-another-script-to-the-rescue&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#yet-another-script-to-the-rescue&quot; aria-label=&quot;Anchor link for: yet-another-script-to-the-rescue&quot;&gt;Yet another script to the rescue&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There is one trick that triggers the error: &lt;strong&gt;opening the script&lt;&#x2F;strong&gt; in the editor.
But it&#x27;s impossible to open all files every time you make a change, by hand.
Given this, a good way to get more errors is to &lt;strong&gt;open all script files, inside a script&lt;&#x2F;strong&gt; ;-)&lt;br &#x2F;&gt;
So I created a script to search and load all &lt;strong&gt;.gd&lt;&#x2F;strong&gt; and &lt;strong&gt;.tscn&lt;&#x2F;strong&gt; files in the project.
This will then trigger some errors, you probably would have missed.
By opening also scene files, you might also catch &lt;strong&gt;dependency errors&lt;&#x2F;strong&gt;, after renaming files for example.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _ready() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	print(&amp;quot;load all scenes...&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	var scene_paths: Array[String] = find_files(&amp;quot;.tscn&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	# load scripts and check for possible dependency errors while loading&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	for path: String in scene_paths:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		var TestScene: PackedScene = load(path)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		assert(TestScene != null)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		var instance: Node = TestScene.instantiate()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		assert(instance != null)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	print(&amp;quot;load all scene done.&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	print(&amp;quot;load all scripts...&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	var script_paths: Array[String] = find_files(&amp;quot;.gd&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	# load scripts and check for possible runtime errors while loading&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	for path: String in script_paths:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		var TestScript: GDScript = load(path)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		assert(TestScript != null)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	print(&amp;quot;load all scripts done.&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func find_files(suffix: String, path: String = &amp;quot;res:&#x2F;&#x2F;&amp;quot;) -&amp;gt; Array[String]:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	var scripts: Array[String] = []&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	var dir: DirAccess = DirAccess.open(path)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	if dir == null:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		print(&amp;quot;error while opening %s&amp;quot; % path)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		return scripts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	dir.list_dir_begin()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	var file_name: String = dir.get_next()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	while not file_name.is_empty():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		var full_path: String = path + file_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		if dir.current_is_dir():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			scripts.append_array(find_files(suffix, full_path + &amp;quot;&#x2F;&amp;quot;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		elif file_name.ends_with(suffix):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			scripts.append(full_path)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		file_name = dir.get_next()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	return scripts&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This script can be executed by being attached to a scene that gets &lt;strong&gt;launched from the editor&lt;&#x2F;strong&gt;.
It can also be invoked from a &lt;strong&gt;bigger test suite&lt;&#x2F;strong&gt;, like I wrote for my game
&lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;99managers-futsal-edition&#x2F;&quot;&gt;99Managers Futsal Edition&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;There I test also &lt;strong&gt;game logic&lt;&#x2F;strong&gt; and make sure that I don&#x27;t make mistakes twice.
It also gives much more confidence, that the code is running as expected, after yet another refactoring session.
I have to admit, I &lt;strong&gt;love refactoring&lt;&#x2F;strong&gt;, so having tests helps a lot to keep the code working as expected.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-s-next&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-s-next&quot; aria-label=&quot;Anchor link for: what-s-next&quot;&gt;What&#x27;s next&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I already extended the script in my game to do even more, like &lt;strong&gt;linting&lt;&#x2F;strong&gt; and checking for
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@dulvui&#x2F;114471590023577302&quot;&gt;dumb mistakes&lt;&#x2F;a&gt;.
But that would be too much for this blog post.
If you still want to check it out, you can find the script on
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;99managers-futsal-edition&#x2F;src&#x2F;commit&#x2F;d1bec8f95cc2e1144c76c64d0e50c7fe76224d4d&#x2F;game&#x2F;src&#x2F;tests&#x2F;test_runtime_errors&#x2F;test_runtime_errors.gd&quot;&gt;Codeberg&lt;&#x2F;a&gt; and
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;99managers-futsal-edition&#x2F;blob&#x2F;57c5b09632ec0ed5005f79d5e88cfd08b1a293cf&#x2F;game&#x2F;src&#x2F;tests&#x2F;test_runtime_errors&#x2F;test_runtime_errors.gd&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Another idea I have is to run it &lt;strong&gt;as main scene&lt;&#x2F;strong&gt; of the game, so it will run every time I launch the game.
If the test passes, the splash screen gets loaded.
Except when the game is not running from the editor, in that case the splash screen will be loaded immediately.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>[Talk] Making FOSS games for fun and (hopefully) profit</title>
          <pubDate>Thu, 03 Apr 2025 08:15:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/make-foss-games/</link>
          <guid>https://simondalvai.org/blog/make-foss-games/</guid>
          <description xml:base="https://simondalvai.org/blog/make-foss-games/">&lt;p&gt;This is the complete blog post to my talk at the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;noi.bz.it&#x2F;en&#x2F;events&#x2F;software-developer-s-thursday&#x2F;4e8d5838-d3e6-4a08-819c-38016cc8f9c7&quot;&gt;Software Developer&#x27;s Thursday&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
It is not a word to word transcript,
but should cover most I said during the talk with some additional notes.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;del&gt;A video will be uploaded to YouTube a few days after the talk and the link will be added here.
But I accidentally used the wrong microphone while recording the talk, so the video has horrible sound and is not ready yet.
I hope to solve the audio issues soon and add the link here.&lt;&#x2F;del&gt;
Sadly there will be no video, the audio quality was simply too bad.&lt;&#x2F;p&gt;
&lt;p&gt;Anyway, let&#x27;s &lt;strong&gt;make some FOSS games!&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;about-me&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#about-me&quot; aria-label=&quot;Anchor link for: about-me&quot;&gt;About me&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Before starting, I want to make clear that &lt;strong&gt;I&#x27;m not a professional&lt;&#x2F;strong&gt; game developer (yet).
I haven&#x27;t made any income with my games and haven&#x27;t worked as game developer yet.
So everything I write here is based on my personal experience as a hobby game developer, with some additional stuff I read on the web.&lt;&#x2F;p&gt;
&lt;p&gt;Everything started with &lt;strong&gt;childhood dreams&lt;&#x2F;strong&gt; since I saw the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Game_Boy&quot;&gt;Nintendo Game Boy&lt;&#x2F;a&gt;
for the first time.
Seeing the infinite possibilities of creating imaginary worlds blew my mind and is fascinating me until to this day.&lt;br &#x2F;&gt;
This experience created the desire to become a game developer.&lt;&#x2F;p&gt;
&lt;p&gt;I learned programming in high-school and worked afterwards as a software developer (as employee and freelance) since &lt;strong&gt;2016&lt;&#x2F;strong&gt;.&lt;br &#x2F;&gt;
In &lt;strong&gt;2017&lt;&#x2F;strong&gt; I started creating my first games with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;libgdx.com&#x2F;&quot;&gt;libGDX&lt;&#x2F;a&gt; in my free time.
In the following &lt;strong&gt;3 years&lt;&#x2F;strong&gt; I created some mobile games.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;color-shooter&#x2F;&quot;&gt;ColorShooter&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;sn4ke&#x2F;&quot;&gt;Sn4ke&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;whatcolor&#x2F;&quot;&gt;WhatColor&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;They where my first attempt to create the next &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Flappy_Bird&quot;&gt;Flappy bird&lt;&#x2F;a&gt; and become rich and famous.
Of course without success.
But it still didn&#x27;t kill my desire and joy to create games.&lt;&#x2F;p&gt;
&lt;p&gt;In &lt;strong&gt;2020&lt;&#x2F;strong&gt; I tried the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;godotengine.org&#x2F;&quot;&gt;Godot Engine&lt;&#x2F;a&gt; and started making games just for fun.
I created the following &lt;strong&gt;2 games&lt;&#x2F;strong&gt; available for mobile, on the web and as flatpaks.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;pocket-broomball&#x2F;&quot;&gt;Pocket Broomball&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;ball2box&#x2F;&quot;&gt;Ball2Box&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;I still tried to make some dollars with ads, but quickly realized that it doesn&#x27;t work.
So I removed all ads and tracking from my games and open sourced all of them, using a copyleft license.&lt;&#x2F;p&gt;
&lt;p&gt;Since September &lt;strong&gt;2024&lt;&#x2F;strong&gt; I&#x27;m working full time on my &lt;strong&gt;first FOSS commercial game&lt;&#x2F;strong&gt;
&lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;99managers-futsal-edition&#x2F;&quot;&gt;99Managers Futsal Edition&lt;&#x2F;a&gt; (still in beta).&lt;br &#x2F;&gt;
I started this game right after Ball2Box in 2021, but I was not able to see how I can finish this game just in my free time.
The decision to quit my job and go all in was not easy, but if not now, when can I work on my childhood dreams?&lt;&#x2F;p&gt;
&lt;p&gt;The plan is to sell the game on Steam and release it on other platforms like itch.io and Flathub for free.
I really care about free and open source software, and I hope also other people do and see that the game industry needs more of it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;problems-with-most-games&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#problems-with-most-games&quot; aria-label=&quot;Anchor link for: problems-with-most-games&quot;&gt;Problems with most games&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Modern games have in my opinion quite some serious problems, that would not exist in FOSS games.
Most players are &lt;strong&gt;children&lt;&#x2F;strong&gt; and they are exposed to malicious practices, mostly for profits.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Ads and user tracking&lt;&#x2F;strong&gt; bring all the privacy issues to the (mostly mobile) gaming world.
Even without consent, apps can track gamers and sell the data to brokers, as showed in this
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;timsh.org&#x2F;tracking-myself-down-through-in-app-ads&#x2F;&quot;&gt;article&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Micro-transactions and loot boxes&lt;&#x2F;strong&gt; are the next big issue.
Loot boxes are illegal in Belgium and many other countries demand higher age rating, real money disclosure, probability disclosure etc...
This &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ec.europa.eu&#x2F;commission&#x2F;presscorner&#x2F;detail&#x2F;en&#x2F;ip_25_831&quot;&gt;EU press release&lt;&#x2F;a&gt;
about &lt;strong&gt;protecting children from harmful practices&lt;&#x2F;strong&gt; shows,
how games are designed to attract and mislead children to spend (lots of) money on games.&lt;&#x2F;p&gt;
&lt;p&gt;And then there are the famous &lt;strong&gt;freemium game&lt;&#x2F;strong&gt;, where tiny fraction of players pay insane amounts of money.
The South Park episode &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.southparkstudios.com&#x2F;episodes&#x2F;jy5lbq&#x2F;south-park-freemium-isn-t-free-season-18-ep-6&quot;&gt;Freemium Isn&#x27;t Free&lt;&#x2F;a&gt;
explains very well how this works.
You can skip forward to 15:12 for the interesting part, but I recommend watching the full episode.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Down the rabbit hole it can get alarming.&lt;&#x2F;strong&gt;
There are even more malicious practices in games, like the German satire show Neo Magazin Royale showed in the episode
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=hTeTjx4k9jQ&quot;&gt;Coin Master - Abzocke mit Fun&lt;&#x2F;a&gt; (in German, auto subs available).
You can read about it also on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Coin_Master#Criticism&quot;&gt;Wikipedia&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
Long story short, it&#x27;s slot machine masquerading as a game that targets children.
They did also a research on who financed the game studio Moon Active, the studio that created Coin Master,
and found that the main investors come from &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;hTeTjx4k9jQ?t=644&quot;&gt;the gambling industry&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
So they are showing children how slot machines work, make them addicted and create the &lt;strong&gt;gamblers of tomorrow&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Of course not &lt;strong&gt;all games&lt;&#x2F;strong&gt; using ads, micro-transactions or similar are pure evil, but many of them are.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;game-development-job-market&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#game-development-job-market&quot; aria-label=&quot;Anchor link for: game-development-job-market&quot;&gt;Game development job market&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Since I showed you the bad part of the gaming industry, let&#x27;s continue with bad news.
Here I want to justify again that I&#x27;m not a professional game developer yet,
and &lt;strong&gt;my knowledge is mostly based on what I see on the web&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Game developers get a &lt;strong&gt;lower pay&lt;&#x2F;strong&gt; than rest of the software industry.&lt;&#x2F;p&gt;
&lt;p&gt;They also have more &lt;strong&gt;working hours&lt;&#x2F;strong&gt; aka crunch time, because there are tough deadlines.&lt;&#x2F;p&gt;
&lt;p&gt;Working in the games industry is also &lt;strong&gt;seen as a privilege&lt;&#x2F;strong&gt;.
So many studios exploit childhood dreams, like mine and get people to work more for less.
Because well, you are working your dream job!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;No jobs in South Tyrol&lt;&#x2F;strong&gt; (the region in Italy I live) and in other locations outside big cities.
I could easily find a job as a common software developer here, but the next game studio is more than 150km away.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Finding remote jobs really difficult&lt;&#x2F;strong&gt; and most studios want people in the office.
There are lots of NDAs that need to be signed, for example to use proprietary SDKs for consoles.
So studios prefer to keep everything in the office, to prevent leaks and other issues.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-foss-games&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-foss-games&quot; aria-label=&quot;Anchor link for: why-foss-games&quot;&gt;Why FOSS games&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So now let&#x27;s see how FOSS games can partially solve this problems.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;strong&gt;Kiwi Free Software CD&lt;&#x2F;strong&gt; was the very first free software I got in elementary school.
It was created by the province of Bolzano for schools to give them access to free (as in free speech and free beer) software.
There is an article in German, Italian and Ladin about the CD on the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;news.provinz.bz.it&#x2F;de&#x2F;news-archive&#x2F;207075&quot;&gt;province&#x27;s website&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
I really enjoyed playing Supertux or becoming a deejay with Audacity.
At the time I didn&#x27;t know what FOSS is and why it is important, but it surely shaped my path as a software developer.&lt;br &#x2F;&gt;
Said that, I&#x27;m convinced that also FOSS games can have this effect and shape the &lt;strong&gt;FOSS developer of the future&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Get quality feedback&lt;&#x2F;strong&gt;, as this happy reddit user showed in his
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;gamedev&#x2F;comments&#x2F;qeqn3b&#x2F;despite_having_just_58_sales_over_38_of_bug&#x2F;&quot;&gt;post&lt;&#x2F;a&gt;.
His game was not FOSS, but by simply releasing the game also for GNU&#x2F;Linux was a success.
His GNU&#x2F;Linux users produced 650% more high quality bug reports.
Also in my experience I saw that once developers discover your game, through F-Droid or Flathub, much more issues get created.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Get contributions&lt;&#x2F;strong&gt; to your game with bug fixes, features and non code parts like translations.
It might be difficult to get code contributions, as many FOSS projects struggle to get contributors.
But in my case I already got my games translated in many other languages, by being FOSS.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Get free access&lt;&#x2F;strong&gt; to paid tools like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;hosted.weblate.org&#x2F;projects&#x2F;99-managers-futsal-edition&#x2F;game&#x2F;&quot;&gt;Weblate&lt;&#x2F;a&gt;,
I&#x27;m currently using for translations.
Weblate gives free hosting to FOSS projects and I want to thank them here once again, for their generous offer!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Give free access&lt;&#x2F;strong&gt; to the game, to give something back to the community.
But also to give access to people who can&#x27;t afford games.
In some countries the monthly average wage is less than what most games costs nowadays.
So this people can&#x27;t play games or need go pirate them.
Being FOSS gives free and safe access to everybody.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;All problems&lt;&#x2F;strong&gt; magically disappear, because if someone does nasty things with FOSS, the project will get forked.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;game-engines&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#game-engines&quot; aria-label=&quot;Anchor link for: game-engines&quot;&gt;Game engines&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now that I convinced you that your next game will be FOSS ;-), let&#x27;s talk about game engines.&lt;&#x2F;p&gt;
&lt;p&gt;It is important to choose the right tool for the development of your game, even if it will be proprietary.&lt;br &#x2F;&gt;
In 2024 &lt;strong&gt;Unity&lt;&#x2F;strong&gt; wanted to introduce a &lt;strong&gt;0.20 cent runtime fee&lt;&#x2F;strong&gt;, for every installation of a Unity game.
After strong critics by the community, Unity canceled the fee.
But many developers understood what it means to be &lt;strong&gt;dependent on a closed project&lt;&#x2F;strong&gt;.
Something like that would never happen with a
(real, no &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Contributor_License_Agreement&quot;&gt;CLA&lt;&#x2F;a&gt;)
open source project.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;The list of game engines&lt;&#x2F;strong&gt; on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;List_of_game_engines&quot;&gt;Wikipedia&lt;&#x2F;a&gt;
has a lot of open source projects that can fit your needs.
Another great website I just found recently is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;enginesdatabase.com&#x2F;&quot;&gt;enginesdatabas.com&lt;&#x2F;a&gt;,
where you can find many possible engines with great filters.&lt;&#x2F;p&gt;
&lt;p&gt;In my opinion, there are &lt;strong&gt;two main categories&lt;&#x2F;strong&gt;: libraries&#x2F;frameworks and full engines.
Like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;libgdx.com&#x2F;&quot;&gt;libGDX&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;godotengine.org&#x2F;&quot;&gt;Godot Engine&lt;&#x2F;a&gt; I already used.&lt;br &#x2F;&gt;
&lt;strong&gt;LibGDX&lt;&#x2F;strong&gt; is a Java library that helps you to create a game, but you need to code everything.
It brings a physics engine, so you don&#x27;t need to code that, but you still need to care about low level stuff like memory management.
And to create UIs you have to code every button&#x27;s size and position, without fancy visual editor.
But you are free to implement the games as you want on a architectural design level.
So it gives you more power and freedom, at the cost of having to code parts that are already solved in full engines.&lt;br &#x2F;&gt;
&lt;strong&gt;Godot&lt;&#x2F;strong&gt; on the other hand brings you a full engine with visual editor and lot&#x27;s of other features.
You can create games much faster and really focus on creating the game, without having to care about low level stuff.
But you are limited to Godot&#x27;s design decisions of using Node based scenes with events&#x2F;signals.&lt;&#x2F;p&gt;
&lt;p&gt;So if you want to learn more about what happens under the hood and have more control over your game, use a library of framework.
If you want to focus on the game and be fast, choose a full engine.
But never forget, the most important part is &lt;strong&gt;making a fun game&lt;&#x2F;strong&gt;, it doesn&#x27;t matter what technologies are used.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;free-as-in-free-speech-assets&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#free-as-in-free-speech-assets&quot; aria-label=&quot;Anchor link for: free-as-in-free-speech-assets&quot;&gt;Free (as in free speech) assets&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Most games are not made by just code, but also use audio and visual assets.
So itis important to know where to find good assets that can be used in FOSS games.&lt;&#x2F;p&gt;
&lt;p&gt;This is my top 3 list, but there are plenty of websites on the web.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;kenney.nl&#x2F;&quot;&gt;kenney.nl&lt;&#x2F;a&gt; 2D, 3D and audio, all CC0&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;opengameart.org&#x2F;&quot;&gt;opengameart.org&lt;&#x2F;a&gt; 2D, 3D and audio, multiple license&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;freesound.org&#x2F;&quot;&gt;freesound.org&lt;&#x2F;a&gt; audio, multiple licenses&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Just keep in mind that you need to have the rights to use and share the assets you get.
You probably can&#x27;t use and distribute assets you can buy online, because they have a proprietary license.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;licenses-and-trademarks&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#licenses-and-trademarks&quot; aria-label=&quot;Anchor link for: licenses-and-trademarks&quot;&gt;Licenses and Trademarks&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now that have the source code and assets, let&#x27;s talk a bit &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Legal_English&quot;&gt;legalese&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;To keep it short, I will just make a quick list of most used licenses.
I highly recommend making your own research on licenses, to make sure you understand them.&lt;br &#x2F;&gt;
You can find a comprehensive list on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Comparison_of_free_and_open-source_software_licenses&quot;&gt;Wikipedia&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;For &lt;strong&gt;source code&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
permissive MIT, Apache&lt;br &#x2F;&gt;
weak copyleft MPL, LGPL&lt;br &#x2F;&gt;
strong copyleft GPL, AGPL&lt;&#x2F;p&gt;
&lt;p&gt;For &lt;strong&gt;assets&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
public domain CC0&lt;br &#x2F;&gt;
attribution CC-BY&lt;br &#x2F;&gt;
attribution and share alike CC-BY-SA&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;reuse.software&#x2F;&quot;&gt;&lt;strong&gt;Reuse tool&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;
to keep track of licenses in your repositories.&lt;br &#x2F;&gt;
It is really easy to get a piece of code or asset from the web and add it to your game.
You just want to try and see it fits, but then a bug appears and you forget about it.
Good luck finding the website months later and hope, that it had a compliant license.&lt;br &#x2F;&gt;
The reuse tool forces you to add &lt;strong&gt;license headers to all files&lt;&#x2F;strong&gt; in a repository.
This makes forgetting things much harder and in the long run it will payoff.&lt;&#x2F;p&gt;
&lt;p&gt;Finally &lt;strong&gt;trademarks&lt;&#x2F;strong&gt; to protect name and branding of your game.
So someone can&#x27;t reuse the name, logo or both (depending on which trademark) in their clones, without your permission.
This is not always necessary and costs quite some money.
But it&#x27;s like an insurance, you hope that you don&#x27;t have to use it, but when it&#x27;s necessary, you are happy to have it.
Especially if you plan to create a commercial game.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;game-distribution-platforms&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#game-distribution-platforms&quot; aria-label=&quot;Anchor link for: game-distribution-platforms&quot;&gt;Game distribution platforms&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Also here I don&#x27;t want to spend to much time, since there are better articles on this topic.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;f-droid.org&#x2F;en&#x2F;&quot;&gt;&lt;strong&gt;F-Droid&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; is a open source dedicated Android App catalog.
It will give you visibility in the open source community and might get you some contributions and donations.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;flathub.org&#x2F;&quot;&gt;&lt;strong&gt;Flathub&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; is a GNU&#x2F;Linux app store for open source and proprietary software.
It allows you to easily bring your game to most GNU&#x2F;Linux distributions.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;itch.io&quot;&gt;&lt;strong&gt;itch.io&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; it a great place for indie games and developers.
You can reach a big audience that will expect unique and small games by solo developers or small studios.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;partner.steampowered.com&quot;&gt;&lt;strong&gt;Steam&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; can give you the visibility and possibility to create a valid commercial game.
Most successful indie developers sell their games on Steam.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;strong&gt;Google Play Store&lt;&#x2F;strong&gt; and &lt;strong&gt;Apple App Store&lt;&#x2F;strong&gt; are also valid platforms, but can be complicated.
It is also really hard to get visibility and make money, since the mobile game market is much different compared to desktop game market.&lt;br &#x2F;&gt;
Just ask yourself when did you buy the last mobile app?
And how much did you spend on your last desktop or console game?&lt;&#x2F;p&gt;
&lt;h2 id=&quot;foss-business-models&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#foss-business-models&quot; aria-label=&quot;Anchor link for: foss-business-models&quot;&gt;FOSS business models&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;No business, just fun&lt;&#x2F;strong&gt; is the best model and surely the one you will have most fun with ;-)&lt;br &#x2F;&gt;
It&#x27;s not really a business model, but I suggest to every beginner to focus on fun and learning.
Leave the business side to the day it makes sense.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Donations&lt;&#x2F;strong&gt; can be a nice way to stay motivated.
There are many platforms, like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;liberapay.com&#x2F;&quot;&gt;liberapay&lt;&#x2F;a&gt;, where people can donate you money.
In my case, I got around 25 Euros in donations overall.
It&#x27;s a real great feeling if a complete stranger gives you a few bucks, because he liked your game.&lt;br &#x2F;&gt;
But it can be really difficult to get so much donations, that you can live from them.
And donations might make paying taxes or similar things more difficult.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Sell desktop games platforms like Steam&lt;&#x2F;strong&gt; is potentially the best way to earn a living as a game developer.
There are several FOSS games that do this and still have free versions on all other platforms.&lt;br &#x2F;&gt;
The best example I found is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mindustrygame.github.io&#x2F;&quot;&gt;Mindustry&lt;&#x2F;a&gt;, that is a GPL licensed tower defense games.
According to an estimation from &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;games-stats.com&#x2F;steam&#x2F;game&#x2F;mindustry&#x2F;&quot;&gt;game-stats.com&lt;&#x2F;a&gt;,
the game made more than 3 million dollars.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;guerilla-marketing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#guerilla-marketing&quot; aria-label=&quot;Anchor link for: guerilla-marketing&quot;&gt;Guerilla marketing&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As with business models, I suggest to care about marketing only when you feel confident about your games.
Learn how to make great games first, than start with the rest.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Write a blog&lt;&#x2F;strong&gt; if you like writing, like me.
I didn&#x27;t like it from the beginning, but later I started really to love to write blog posts.
That passion survived also the rise of LLMs, so my blogs are still written by typing letter by letter by me.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Make videos&lt;&#x2F;strong&gt; if you prefer that.
It&#x27;s important to have a web presence in some way, it doesn&#x27;t really matter the format.
People can stumble upon your games only if there is a way to do it.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;FOSS lists&lt;&#x2F;strong&gt; are a great way to get visibility for free without lifting a finger.&lt;br &#x2F;&gt;
If your games is FOSS and has an audience, somebody will add your games to this lists.
My games got added to the following (but not only) lists&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;godotengine&#x2F;awesome-godot&quot;&gt;awesome-godot&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fossdroid.com&#x2F;a&#x2F;ball2box.html&quot;&gt;fossdroid&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fossgaming.codeberg.page&#x2F;games&#x2F;pocket-broomball&#x2F;&quot;&gt;fossgaming&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;&lt;strong&gt;Niche games&lt;&#x2F;strong&gt; bring natural visibility.
Pick something unique nobody has created yet, and you will get downloads.&lt;br &#x2F;&gt;
I saw this happen with Pocket Broomball, because it was and still is the only Broomball video game.
And I hope to get the same effect with 99Managers Futsal Edition.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Stickers, stickers, stickers&lt;&#x2F;strong&gt; are cheap and are loved by everyone.
Once you have a logo, print stickers and don&#x27;t forget to bring them to events and whenever you leave the house.
The cheapest way I found is to print them on sticky paper with a ordinary printer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-game-development-advice&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-game-development-advice&quot; aria-label=&quot;Anchor link for: my-game-development-advice&quot;&gt;My game development advice&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;strong&gt;Start with small games&lt;&#x2F;strong&gt; and finish them.
The first games are great to learn how to make games.
You will notice that your second game is already much easier to make and is much better organized.
To not talk about the code quality.
I always get embarrassed when I have to fix a bug for Pocket Broomball and have to see the code I wrote a few years ago.&lt;br &#x2F;&gt;
Working immediately on big games can bring a lot of frustration and you will probably never finish it.
Making something small, finishing it and being proud of it is much better to stay motivated.
Once you feel confident, you can use your skills to create bigger games.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Make web or desktop games&lt;&#x2F;strong&gt;, because it is easier to release and get feedback.
Releasing mobile games can be really difficult, if you have no experience with it.
And your game will just be one of out of billions.
It can also get quite frustrating when Google&#x2F;Apple decide to remove your perfectly working game from the market,
if you don&#x27;t update to the latest SDK.
itch.io is a much more beginner friendly platform for Web, Desktop and even Android.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;No gaming computer&#x2F;laptop is needed&lt;&#x2F;strong&gt; for game development.
I created my first games with libGDX on a tiny 11inch laptop with 4gb of ram and an Intel Celeron.
Just if you want to create a open world 3D game or similar a graphic card might be needed.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Participate in game jams&lt;&#x2F;strong&gt; online on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;itch.io&#x2F;jams&quot;&gt;itch.io&lt;&#x2F;a&gt; or
offline in South Tyrol like &lt;strong&gt;castle game jam&lt;&#x2F;strong&gt; organized by &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.gameground.it&#x2F;&quot;&gt;gameground&lt;&#x2F;a&gt;
or the &lt;strong&gt;dung game jam&lt;&#x2F;strong&gt; organized by &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.dung-gaming.it&#x2F;&quot;&gt;dung-gaming&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
Personally I don&#x27;t like competitive coding competitions, but it&#x27;s a great place to meet like minded people and create games!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;99managers-roadmap&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#99managers-roadmap&quot; aria-label=&quot;Anchor link for: 99managers-roadmap&quot;&gt;99Managers roadmap&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here a tiny roadmap of my next milestones regarding 99Managers.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;2025&lt;&#x2F;strong&gt; release Futsal Edition on Steam and other platforms&lt;br &#x2F;&gt;
&lt;strong&gt;2025&lt;&#x2F;strong&gt; &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sfscon.it&quot;&gt;SFSCon&lt;&#x2F;a&gt; talk proposal&lt;br &#x2F;&gt;
&lt;strong&gt;2026&lt;&#x2F;strong&gt; adapt code for other team sport&lt;br &#x2F;&gt;
&lt;strong&gt;2027&lt;&#x2F;strong&gt; and many other team sports&lt;br &#x2F;&gt;
&lt;strong&gt;2030&lt;&#x2F;strong&gt; ALL team sports ;-)&lt;br &#x2F;&gt;
...and of course, plans are made to be broken.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;99managers-gameplay&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#99managers-gameplay&quot; aria-label=&quot;Anchor link for: 99managers-gameplay&quot;&gt;99Managers gameplay&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;During the talk I showed the gameplay of my game.
You can watch the video (when it is available) or simply play the game.
The up to date download links are available &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;99managers-futsal-edition&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Duplicate Godot custom resources deeply, for real</title>
          <pubDate>Tue, 18 Mar 2025 15:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-duplicate-resources/</link>
          <guid>https://simondalvai.org/blog/godot-duplicate-resources/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-duplicate-resources/">&lt;p&gt;Resources in Godot are &lt;strong&gt;really powerful&lt;&#x2F;strong&gt; and can make a Game Devs life easier in many ways.
If you haven&#x27;t used them yet, I can only recommend reading the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;scripting&#x2F;resources.html&quot;&gt;official docs&lt;&#x2F;a&gt;
or my &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;godot-custom-resources&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt; about them.&lt;&#x2F;p&gt;
&lt;p&gt;Now I use them a lot, especially in &lt;strong&gt;bigger projects&lt;&#x2F;strong&gt; with many different data models.
At some point, you might want to duplicate a resource using the duplicate() method.
Here things got complicated for me.&lt;br &#x2F;&gt;
Reading the documentation would have saved me hours of debugging, and writing this blog post.
But I didn&#x27;t expect that their duplicate() method works much different as in other object oriented programming languages.&lt;&#x2F;p&gt;
&lt;p&gt;The full source code in this article can be found on
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;simondalvai.org&#x2F;src&#x2F;branch&#x2F;main&#x2F;sandbox&#x2F;duplicate-resources&#x2F;&quot;&gt;Coderberg&lt;&#x2F;a&gt;
and on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;simondalvai.org&#x2F;tree&#x2F;main&#x2F;sandbox&#x2F;duplicate-resources&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Note: This blog post was written using &lt;strong&gt;Godot 4.x&lt;&#x2F;strong&gt; (version 4.4 to be precise) and things could break with further versions.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;create-custom-resources&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#create-custom-resources&quot; aria-label=&quot;Anchor link for: create-custom-resources&quot;&gt;Create custom resources&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I will simply reuse some reduced resources from my open-source game &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;99managers-futsal-edition&#x2F;&quot;&gt;99Managers Futsal Edition&lt;&#x2F;a&gt;.
There we have &lt;strong&gt;futsal players&lt;&#x2F;strong&gt; with a name and surname.
(For who doesn&#x27;t know &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Futsal&quot;&gt;Futsal&lt;&#x2F;a&gt; yet, it&#x27;s 5 a side soccer indoors)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name Player&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var name: String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var surname: String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# custom resources need a _init() method with default values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# to work as expected inside Godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _init(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    p_name: String = &amp;quot;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    p_surname: String = &amp;quot;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;) -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name = p_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    surname = p_surname&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s see how Resources can be duplicated in Godot.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;simple-references&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#simple-references&quot; aria-label=&quot;Anchor link for: simple-references&quot;&gt;Simple references&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The most trivial way to make two resources from one, is to assign it to a new variable.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var player_1: Player = Player.new(&amp;quot;Gianluigi&amp;quot;, &amp;quot;Buffon&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var player_2: Player = player_1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This creates a &lt;strong&gt;reference&lt;&#x2F;strong&gt; of the resource that still points to the same resource and &lt;strong&gt;no duplication&lt;&#x2F;strong&gt; takes place.
This can be useful if you want to keep a pointer to a nested resource for easier access.&lt;&#x2F;p&gt;
&lt;p&gt;But how can we verify, that they are the same?
Every resource in Godot has an unique id, aka &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;classes&#x2F;class_rid.html&quot;&gt;RID&lt;&#x2F;a&gt;,
that can be accessed with the &lt;strong&gt;get_rid()&lt;&#x2F;strong&gt; function.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# True, since both have the same RIDs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(player_1.get_rid() == player_2.get_rid())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# changing player_1&amp;#39;s properties, will automatically also change player_2&amp;#39;s properties&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;player_1.name = &amp;quot;Alessandro&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;player_1.surname = &amp;quot;Del Piero&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# True, because both variables point to the changed resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(player_1.surname == player_2.surname)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;shallow-copy-with-duplicate&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#shallow-copy-with-duplicate&quot; aria-label=&quot;Anchor link for: shallow-copy-with-duplicate&quot;&gt;Shallow copy with duplicate()&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Using &lt;strong&gt;duplicate()&lt;&#x2F;strong&gt; function creates a copy of the resource.
This function is also present in other classes, like Dictionary and Array.&lt;&#x2F;p&gt;
&lt;p&gt;To show how duplicate works, a more complicated resource is needed.
So let&#x27;s create a team with a goalkeeper, that is a player.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name Team&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var name: String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var goalkeeper: Player&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var field_players: Array[Player]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _init(&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    p_name: String = &amp;quot;&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    p_goalkeeper: Player = Player.new(),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    p_field_players: Array[Player] = [],&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;) -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    name = p_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    goalkeeper = p_goalkeeper&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    field_players = p_field_players&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;&#x2F;strong&gt; to know is that only resources with the &lt;strong&gt;@export&lt;&#x2F;strong&gt; annotation get deeply duplicated.
Additionally, this method will fail if &lt;strong&gt;_init()&lt;&#x2F;strong&gt; has been defined with &lt;strong&gt;required parameters&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now let&#x27;s create a team and see how it duplicates.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Let&amp;#39;s instantiate a team with a goalkeeper&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var team_1: Team = Team.new(&amp;quot;Italy&amp;quot;, Player.new(&amp;quot;Gianluigi&amp;quot;, &amp;quot;Buffon&amp;quot;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# and a copy of it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var team_2: Team = team_1.duplicate()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;team_2.name = &amp;quot;Italy copy&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# True, because both teams are unique and independent resources&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(team_1.name != team_2.name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Let&amp;#39;s change team_2&amp;#39;s goalkeeper name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;team_2.goalkeeper.name = &amp;quot;Ganluigi&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# True, because both are named Gianluigi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(team_1.goalkeeper.name == team_2.goalkeeper.name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Let&amp;#39;s change team_2&amp;#39;s goalkeeper surname&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;team_2.goalkeeper.surname = &amp;quot;Donnarumma&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Also true, because the team_2&amp;#39;s goalkeeper is a reference of the team_1&amp;#39;s goalkeeper&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(team_1.goalkeeper.surname == team_2.goalkeeper.surname)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So duplicate() creates a &lt;strong&gt;unique and independent resources&lt;&#x2F;strong&gt;, but all sub-resources will be &lt;strong&gt;shallow copies&lt;&#x2F;strong&gt;.
This means they are only references.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;deep-copy-with-duplicate-true&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#deep-copy-with-duplicate-true&quot; aria-label=&quot;Anchor link for: deep-copy-with-duplicate-true&quot;&gt;Deep copy with duplicate(true)&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The duplicate method has a boolean parameter called &lt;strong&gt;subresources&lt;&#x2F;strong&gt;, if set true, all sub-resources are also duplicated.
So when using the same code from the previous section, the goalkeeper will also be duplicated.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Let&amp;#39;s instantiate a team with a goalkeeper&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var team_1: Team = Team.new(&amp;quot;Italy&amp;quot;, Player.new(&amp;quot;Gianluigi&amp;quot;, &amp;quot;Buffon&amp;quot;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# and a copy of it, with sub-resources set to true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var team_2: Team = team_1.duplicate(true)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;team_2.name = &amp;quot;Italy copy&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Still true, because both teams are unique and independent resources&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(team_1.name != team_2.name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;team_2.goalkeeper.name = &amp;quot;Gianluigi&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# True, because both still are named Gianluigi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(team_1.goalkeeper.name == team_2.goalkeeper.name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;team_2.goalkeeper.surname = &amp;quot;Donnarumma&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# True, because the team_2&amp;#39;s goalkeeper NO LONGER is a reference of the team_1&amp;#39;s goalkeeper&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(team_1.goalkeeper.surname != team_2.goalkeeper.surname)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;real-deep-copy&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#real-deep-copy&quot; aria-label=&quot;Anchor link for: real-deep-copy&quot;&gt;Real deep copy&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Great, we can now duplicate resources now with all properties.
Well, actually &lt;strong&gt;not all of them&lt;&#x2F;strong&gt;.&lt;br &#x2F;&gt;
The documentation reads: &quot;Subresources inside Array and Dictionary properties are &lt;strong&gt;never&lt;&#x2F;strong&gt; duplicated.&quot;
So there is currently no way to deeply duplicate a resource, with ALL it&#x27;s sub-resources, using Godot&#x27;s methods.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# Lets create once again two players&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var goalkeeper: Player = Player.new(&amp;quot;Gianluigi&amp;quot;, &amp;quot;Buffon&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var player_1: Player = Player.new(&amp;quot;Paolo&amp;quot;, &amp;quot;Maldini&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var player_2: Player = Player.new(&amp;quot;Alessandro&amp;quot;, &amp;quot;Del Piero&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# and a team with the two players&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var team_1: Team = Team.new(&amp;quot;Italy&amp;quot;, goalkeeper, [player_1, player_2])&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now we have a resource (team) with an Array of sub-resources (players).
Let&#x27;s make some tests.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var team_2: Team = team_1.duplicate(true)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;team_2.name = &amp;quot;Italy copy&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# lets change a players name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;team_2.players[0].name = &amp;quot;Daniele&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(team_1.surname != team_2.surname)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# True, because both player arrays still are the same resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(team_1.players[0].name == team_2.players[0].name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So let&#x27;s create a custom method to cover this special case.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func duplicate_deep() -&amp;gt; Team:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	var copy: Team = duplicate(true)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	copy.players = []&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	for player: Player in field_players:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		copy.players.append(player.duplicate(true))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	return copy&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Using this custom duplicate_deep() method, the tests from above will work as expected.
The same approach works with Dictionaries.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var team_deep: Team = team_1.duplicate_deep()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;team_deep.name = &amp;quot;Italy copy&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# lets change a players surname&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;team_deep.players[0].name = &amp;quot;Daniele&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# True&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(team_1.surname != team_deep.surname)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# True, because both players are unique resources&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;assert(team_1.players[0].name != team_deep.players[0].name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here you can find the
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;classes&#x2F;class_resource.html#class-resource-method-duplicate&quot;&gt;official documentation&lt;&#x2F;a&gt;
of the duplicate method.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;in-the-meantime-my-code-changed&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#in-the-meantime-my-code-changed&quot; aria-label=&quot;Anchor link for: in-the-meantime-my-code-changed&quot;&gt;In the meantime, my code changed&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;When I started writing this, I had the necessity to deeply duplicate resources.
In the meantime I refactored parts of the code to &lt;strong&gt;avoid using duplicates&lt;&#x2F;strong&gt;.&lt;br &#x2F;&gt;
This makes everything a lot easier to understand and to maintain.
I still want to share how it is possible, but highly recommend to check twice &lt;strong&gt;if it is really needed&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Said that, I also highly recommend to read the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;&quot;&gt;&lt;strong&gt;official documentation&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;, as much as possible.
Godot has a really amazing documentation, with the class reference also included offline in the editor.
So even with no&#x2F;low internet connections, you are covered.&lt;br &#x2F;&gt;
And to be honest, if I should have read the duplicate methods documentation better in the first place.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;summary&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#summary&quot; aria-label=&quot;Anchor link for: summary&quot;&gt;Summary&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So the most important things to keep in mind when duplicating resources are&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;_init()&lt;&#x2F;strong&gt; with default parameters&lt;&#x2F;li&gt;
&lt;li&gt;Only &lt;strong&gt;@export&lt;&#x2F;strong&gt; annotated properties get duplicated&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;duplicate()&lt;&#x2F;strong&gt; creates copy of built-in properties, but references to sub-resources&lt;&#x2F;li&gt;
&lt;li&gt;&lt;strong&gt;duplicate(true)&lt;&#x2F;strong&gt; creates copy of all properties also sub-resources, except Arrays and Dictionaries&lt;&#x2F;li&gt;
&lt;li&gt;A &lt;strong&gt;custom method&lt;&#x2F;strong&gt; is needed, to duplicate Arrays and Dictionaries&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>I Love Free Software Day 2025</title>
          <pubDate>Fri, 14 Feb 2025 11:50:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/ilovefs-day-2025/</link>
          <guid>https://simondalvai.org/blog/ilovefs-day-2025/</guid>
          <description xml:base="https://simondalvai.org/blog/ilovefs-day-2025/">&lt;p&gt;It&#x27;s been a long time since I wanted to share a list of FOSS projects I really enjoy.
Today is prefect for this, because it&#x27;s &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fsfe.org&#x2F;activities&#x2F;ilovefs&#x2F;&quot;&gt;I Love Free Software Day&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;This list would be enormous, if I would really cover every FOSS project I love and use.
So I decided to limit this post to &lt;strong&gt;three projects&lt;&#x2F;strong&gt; and repeat this process every year on the 14th of February.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lichess&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#lichess&quot; aria-label=&quot;Anchor link for: lichess&quot;&gt;Lichess&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The web can be full off ads, privacy invading trackers and proprietary software.
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lichess.org&quot;&gt;Lichess&lt;&#x2F;a&gt; is the opposite of this and offers free (as in free beer and free speech) &lt;strong&gt;online chess&lt;&#x2F;strong&gt;.
You can play it on Android, iOS and in the Web as an anonymous player or with an account.
&lt;strong&gt;All features are available for free&lt;&#x2F;strong&gt;, even post-game evaluation with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stockfishchess.org&#x2F;&quot;&gt;Stockfish&lt;&#x2F;a&gt; in the cloud.
The only difference to users that have donated to the project, are wings near the user name.&lt;br &#x2F;&gt;
As of today, and I really didn&#x27;t expect this, my &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lichess.org&#x2F;@&#x2F;dulvui&quot;&gt;account&lt;&#x2F;a&gt; states &quot;Time spent playing: 34 days, 23 hours&quot;,
and many more to come!&lt;&#x2F;p&gt;
&lt;p&gt;The projects uses mainly copyleft licenses like GPL and APGL and is a registered French non-profit.
It has no &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Contributor_License_Agreement&quot;&gt;Contributor License Agreement&lt;&#x2F;a&gt;
and this makes the project truly Free Software and resistant to for-profit take overs.&lt;&#x2F;p&gt;
&lt;p&gt;To support the Lichess, you can &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lichess.org&#x2F;patron&quot;&gt;donate&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lichess-org&quot;&gt;contribute&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godot&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#godot&quot; aria-label=&quot;Anchor link for: godot&quot;&gt;Godot&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The Godot Engine is a MIT licensed &lt;strong&gt;game engine&lt;&#x2F;strong&gt; capable of 2D and 3D graphics.
It also has a innovative game &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;getting_started&#x2F;introduction&#x2F;godot_design_philosophy.html&quot;&gt;design philosophy&lt;&#x2F;a&gt;,
that makes game development a real joy.
&lt;strong&gt;In a nutshell&lt;&#x2F;strong&gt;, a Godot game consists of &lt;strong&gt;scenes&lt;&#x2F;strong&gt;, that can have multiple &lt;strong&gt;nodes&lt;&#x2F;strong&gt; connected trough &lt;strong&gt;signals&lt;&#x2F;strong&gt;.
A scene might be the game menu screen, a node the play button and the signal would be the button press action.&lt;&#x2F;p&gt;
&lt;p&gt;This is just a guess out of the wild, but I think the gaming industry is one of the biggest &quot;non-free&quot; software ecosystem out there.
One of the most notable exceptions are Lichess and Godot, of course :-)&lt;br &#x2F;&gt;
I strongly hope this will change in the future and there will be more Free and Open Source games and tools.&lt;&#x2F;p&gt;
&lt;p&gt;The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;godot.foundation&#x2F;&quot;&gt;Godot Foundation&lt;&#x2F;a&gt; is a Dutch non-profit organization.
Also here, no Contributor License Agreement exists.
So this project thrives to remain free and open to it&#x27;s community for a long time.&lt;&#x2F;p&gt;
&lt;p&gt;To support the Godot Engine, you can &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fund.godotengine.org&#x2F;&quot;&gt;donate&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;contributing&#x2F;how_to_contribute.html&quot;&gt;contribute&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;codeberg&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#codeberg&quot; aria-label=&quot;Anchor link for: codeberg&quot;&gt;Codeberg&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The last year I started to host the source code of my projects on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&quot;&gt;Codeberg&lt;&#x2F;a&gt;, a community driven and open-source &lt;strong&gt;git platform&lt;&#x2F;strong&gt;.
I still push my code to the proprietary octopus-branded git platform, but Codeberg is my new origin.&lt;&#x2F;p&gt;
&lt;p&gt;Behind the scenes it uses &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;&quot;&gt;Forgejo&lt;&#x2F;a&gt;, a Gitea fork, that the Codeberg organization created,
after a for-profit company &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;forgejo.org&#x2F;compare-to-gitea&#x2F;&quot;&gt;took it over&lt;&#x2F;a&gt;.
So if someday, you want to host your own &quot;Codeberg&quot; instance, you actually can by hosting a Forgejo server.&lt;&#x2F;p&gt;
&lt;p&gt;Similar to Lichess and Godot, also Codeberg is a registered non-profit association in Germany
and has no Contributor License Agreement.
All the source code of Forgejo has the AGPL license, making it also a real Open Source project.&lt;&#x2F;p&gt;
&lt;p&gt;To support Codeberg, you can &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;donate.codeberg.org&#x2F;&quot;&gt;donate&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;Codeberg&#x2F;Contributing&quot;&gt;contribute&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;spread-the-love&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#spread-the-love&quot; aria-label=&quot;Anchor link for: spread-the-love&quot;&gt;Spread the love&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Free Software projects often don&#x27;t promote themselves much, because of small budgets, missing marketing skills or they simply don&#x27;t want to.
That makes it so important, to celebrate days like this and &lt;strong&gt;show the world&lt;&#x2F;strong&gt; what Free Software is and why it matters.
And also on every other day of the year, we can recommend free and open alternatives, especially to non-technical people.
Organic growth is the best way to bring new people to this community.&lt;br &#x2F;&gt;
We all know how your family and friends can&#x27;t wait for the moment, you finally install them Debian on their machines ;-)&lt;&#x2F;p&gt;
&lt;p&gt;With this, I want to &lt;strong&gt;thank the whole Free Software community&lt;&#x2F;strong&gt; and the ones that will join today.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Neovim as External Editor for Godot</title>
          <pubDate>Sun, 19 Jan 2025 09:53:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-neovim/</link>
          <guid>https://simondalvai.org/blog/godot-neovim/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-neovim/">&lt;p&gt;Since some months now, I&#x27;m happily using Neovim as an &lt;strong&gt;external editor&lt;&#x2F;strong&gt; with Godot Engine 3 and 4.
Godot&#x27;s internal text editor is fine, but my desire to use Neovim was too big.&lt;&#x2F;p&gt;
&lt;p&gt;This blog post covers a &lt;strong&gt;minimal setup&lt;&#x2F;strong&gt; to get Neovim working with Godot.
So you can integrate it directly to your existing configuration or use it as a starting point.&lt;&#x2F;p&gt;
&lt;p&gt;Please note that some minimal knowledge about &lt;strong&gt;Linux and Neovim config files&lt;&#x2F;strong&gt; is needed to follow this blog post.&lt;&#x2F;p&gt;
&lt;p&gt;Technically you can also &lt;strong&gt;just use Godot with vanilla Vim&#x2F;Neovim&lt;&#x2F;strong&gt; with no further changes.
But you might miss some features like &lt;strong&gt;opening files&lt;&#x2F;strong&gt; when clicked in the file explorer or &lt;strong&gt;LSP support&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;So lets set this up to let Godot add some magic to Neovim.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;neovim-server-mode&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#neovim-server-mode&quot; aria-label=&quot;Anchor link for: neovim-server-mode&quot;&gt;Neovim server mode&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Before you can set Neovim as external editor in Godot, you need to start Neovim in server mode.
Additionally to that, a &lt;strong&gt;pipe file&lt;&#x2F;strong&gt; is needed, where Godot can send commands to Neovim.&lt;br &#x2F;&gt;
Add the following code to the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;neovim.io&#x2F;doc&#x2F;user&#x2F;lua-guide.html#lua-guide-config&quot;&gt;&lt;strong&gt;init.lua&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; paths to check for project.godot file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; paths_to_check&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&#x2F;..&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; is_godot_project&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; godot_project_path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; cwd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;getcwd&lt;&#x2F;span&gt;&lt;span&gt;()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; iterate over paths and check&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; key&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; pairs&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;paths_to_check&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;do&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;uv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;fs_stat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cwd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; value&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;project.godot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        is_godot_project&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        godot_project_path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; cwd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        break&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; check if server is already running in godot project path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; is_server_running&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;uv&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;fs_stat&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;godot_project_path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&#x2F;server.pipe&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; start server, if not already running&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; is_godot_project&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; not&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; is_server_running&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fn&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;serverstart&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;godot_project_path&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; ..&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&#x2F;server.pipe&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This code iterates over paths_to_check and tries to find a &quot;project.godot&quot; file.
Then it checks if a server is already running.&lt;br &#x2F;&gt;
I use this approach, because in my projects I separate the code in a &quot;src&#x2F;&quot; directory.
In my case the project.godot file is located in the parent directory.
Additionally multiple Neovim instances can run, without causing errors or conflicts.&lt;br &#x2F;&gt;
You can adapt the paths to check to your needs.&lt;&#x2F;p&gt;
&lt;p&gt;Note that now a variable &lt;strong&gt;is_godot_project&lt;&#x2F;strong&gt; exists and allows to check if a Godot project is opened.
This can get very handy to start the Godot LSP client, only for Godot projects or similar Godot specific configuration.
No worries, this will be covered later in this blog post.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godot-editor-settings&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#godot-editor-settings&quot; aria-label=&quot;Anchor link for: godot-editor-settings&quot;&gt;Godot Editor Settings&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now Neovim is ready to be set as external editor in &lt;strong&gt;Editor Settings &amp;gt; Text Editor &amp;gt; External&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;img class=&quot;image-wide&quot; src=&quot;godot-editor-settings.webp&quot; alt=&quot;A screenshot of Godot&#x27;s Editor Settings for external Text Editors&quot;&gt;
&lt;p&gt;There you need to set the following values:&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Enable &lt;strong&gt;Use External Editor&lt;&#x2F;strong&gt;.&lt;&#x2F;li&gt;
&lt;li&gt;Set &lt;strong&gt;Exec Path&lt;&#x2F;strong&gt; to the Neovim path.&lt;&#x2F;li&gt;
&lt;li&gt;Set &lt;strong&gt;Exec Flags&lt;&#x2F;strong&gt; to the following line.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;--server&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; {project}&#x2F;server.pipe&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;-remote-send&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;C-\&amp;gt;&amp;lt;C-N&amp;gt;:e {file}&amp;lt;CR&amp;gt;:call cursor({line}+1,{col})&amp;lt;CR&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This line will make Neovim open the &lt;strong&gt;file&lt;&#x2F;strong&gt; in a buffer and move your cursor to the indicated &lt;strong&gt;line&lt;&#x2F;strong&gt; and &lt;strong&gt;column&lt;&#x2F;strong&gt;.
The &lt;strong&gt;+1&lt;&#x2F;strong&gt; in &lt;code&gt;cursor({line}+1)&lt;&#x2F;code&gt; is to go to the correct line.
For some reason without +1, the line above is selected.&lt;br &#x2F;&gt;
The &lt;strong&gt;{project}&lt;&#x2F;strong&gt; keyword instead stands for the Godot project path.&lt;&#x2F;p&gt;
&lt;p&gt;Now you can use Neovim as external editor in Godot and &lt;strong&gt;open files&lt;&#x2F;strong&gt; with it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lsp-support&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#lsp-support&quot; aria-label=&quot;Anchor link for: lsp-support&quot;&gt;LSP support&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Godot has a built-in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;editor&#x2F;external_editor.html#lsp-dap-support&quot;&gt;&lt;strong&gt;L&lt;&#x2F;strong&gt;anguage &lt;strong&gt;S&lt;&#x2F;strong&gt;erver &lt;strong&gt;P&lt;&#x2F;strong&gt;rotocol&lt;&#x2F;a&gt;,
that gives you features like &lt;strong&gt;code competition&lt;&#x2F;strong&gt;, &lt;strong&gt;error highlights&lt;&#x2F;strong&gt; and &lt;strong&gt;function definition lookups&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Note: Neovim v0.11 changed how lsp are setup.
Follow the setup guide, depending on which version you use.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;neovim-v0-11-or-later&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#neovim-v0-11-or-later&quot; aria-label=&quot;Anchor link for: neovim-v0-11-or-later&quot;&gt;Neovim v0.11 or later&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Since v0.11 no nvim-lspconfig is needed, but can still be used if you want to.
Without the plugin, you need to create your own config.
I simply copied the default config from
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;nvim-lspconfig&#x2F;blob&#x2F;master&#x2F;lsp&#x2F;gdscript.lua&quot;&gt;Github&lt;&#x2F;a&gt;
to the file **.config&#x2F;nvim&#x2F;lsp&#x2F;gdscript.lua`.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;@brief&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; https:&#x2F;&#x2F;github.com&#x2F;godotengine&#x2F;godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;---&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Language server for GDScript, used by Godot Engine.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; os.getenv&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;GDScript_Port&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;or&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;6005&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; cmd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lsp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;rpc&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;connect&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;127.0.0.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;tonumber&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;port&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;---&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;@type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);font-style: italic;&quot;&gt; vim.lsp.Config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;return&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  cmd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; cmd&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  filetypes&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;gd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;gdscript&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;gdscript3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  root_markers&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; { &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;project.godot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then you can enable the configuration in your &lt;strong&gt;init.lua&lt;&#x2F;strong&gt; file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lsp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;config&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;gdscript&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, {})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;lsp&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;enable&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;gdscript&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;neovim-v0-10-or-older&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#neovim-v0-10-or-older&quot; aria-label=&quot;Anchor link for: neovim-v0-10-or-older&quot;&gt;Neovim v0.10 or older&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;First you need to install the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;nvim-lspconfig&quot;&gt;Neovim LSP plugin&lt;&#x2F;a&gt; and set it up.
I will use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;junegunn&#x2F;vim-plug&quot;&gt;vim-plug&lt;&#x2F;a&gt; as my plugin manager.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Installation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;neovim&#x2F;nvim-lspconfig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; lspconfig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;lspconfig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; godot lsp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; is_godot_project&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; setup lsp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    lspconfig&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;gdscript&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setup&lt;&#x2F;span&gt;&lt;span&gt; {}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;use-the-lsp&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#use-the-lsp&quot; aria-label=&quot;Anchor link for: use-the-lsp&quot;&gt;Use the lsp&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Now you can access all special features when opening GDScript files.&lt;br &#x2F;&gt;
You can try code competition with &lt;strong&gt;Ctrl + x&lt;&#x2F;strong&gt; and &lt;strong&gt;Ctrl + o&lt;&#x2F;strong&gt;.
This will suggest also all class names, function names etc in your Godot project.&lt;br &#x2F;&gt;
With &lt;strong&gt;Ctrl + ]&lt;&#x2F;strong&gt; you can jump to the definition of a function.&lt;&#x2F;p&gt;
&lt;p&gt;There can be &lt;strong&gt;issues&lt;&#x2F;strong&gt; with the LSP, like auto complete giving no results.
In this case you can try &lt;strong&gt;restarting&lt;&#x2F;strong&gt; the LSP plugin with the command &lt;strong&gt;:LspRestart&lt;&#x2F;strong&gt;, or simply restart Neovim.&lt;&#x2F;p&gt;
&lt;p&gt;For the best experience, I recommend running the &lt;strong&gt;LSP in it&#x27;s own thread&lt;&#x2F;strong&gt;.
It can be done by setting &lt;strong&gt;Editor Settings &amp;gt; Network &amp;gt; Language Server &amp;gt; Use Thread&lt;&#x2F;strong&gt; to true.
This reduces the need to restart the LSP a lot.&lt;&#x2F;p&gt;
&lt;p&gt;Keep in mind that the LSP runs within Godot, so you need a running editor instance with your project open.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;treesitter&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#treesitter&quot; aria-label=&quot;Anchor link for: treesitter&quot;&gt;Treesitter&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To get &lt;strong&gt;better&lt;&#x2F;strong&gt; colored code highlighting, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nvim-treesitter&#x2F;nvim-treesitter&quot;&gt;Treesitter&lt;&#x2F;a&gt; does a perfect job.
This plugin does also a lot of other things, like building a tree structure of your code.
Other plugins might use that tree for better manipulation of your code.&lt;br &#x2F;&gt;
But I use it only for nicer colors (probably, I&#x27;m not sure).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Installation&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;nvim-treesitter&#x2F;nvim-treesitter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, { [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;do&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:TSUpdate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Setup&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;require&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;nvim-treesitter.configs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setup&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    ensure_installed&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;gdscript&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;godot_resource&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;gdshader&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    highlight&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        enable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; disable auto install of languages when opening files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    auto_install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; disable for files bigger than 100 KB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    disable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;lang&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; buf&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; max_filesize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1024&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 100 KB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ok&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; pcall&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;loop&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fs_stat&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_buf_get_name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ok&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; max_filesize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    end&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This setup of treesitter includes also some configuration.
The plugins gets &lt;strong&gt;disabled&lt;&#x2F;strong&gt; for files bigger than 100KB, to keep opening Neovim fast.
With &lt;strong&gt;auto_install = false&lt;&#x2F;strong&gt;, new languages don&#x27;t get installed automatically, when opening a file of the respective language.
Only the languages defined in &lt;strong&gt;ensure_installed&lt;&#x2F;strong&gt; are installed.&lt;&#x2F;p&gt;
&lt;p&gt;Here you can see a side by side comparison of Treesitter &lt;strong&gt;disabled on the left&lt;&#x2F;strong&gt; and &lt;strong&gt;enabled on the right&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;img class=&quot;image-wide&quot; src=&quot;treesitter.webp&quot; alt=&quot;A screenshot a side by side comparison of Treesitter disabled on the left and enabled on the right in Neovim &quot;&gt;
&lt;p&gt;Neovim already can colorize some of the code, but Treesitter can do it better.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;debugging&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#debugging&quot; aria-label=&quot;Anchor link for: debugging&quot;&gt;Debugging&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Godot has a built-in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;editor&#x2F;external_editor.html#lsp-dap-support&quot;&gt;&lt;strong&gt;D&lt;&#x2F;strong&gt;ebug&lt;strong&gt;A&lt;&#x2F;strong&gt;dapter&lt;strong&gt;P&lt;&#x2F;strong&gt;rotocol&lt;&#x2F;a&gt;,
so it is directly integrated with Godot, exactly as the LSP.
There are many Neovim Debug plugins out there, if you are already familiar with one, it&#x27;s worth to check out if it supports Godot.&lt;&#x2F;p&gt;
&lt;p&gt;While writing this blog post, I used to have &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;mfussenegger&#x2F;nvim-dap&quot;&gt;nvim-dap&lt;&#x2F;a&gt; installed.
This can attach to Godot&#x27;s DAP and allow you to set breakpoints or run the game from Neovim.
Then I also tried &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rcarriga&#x2F;nvim-dap-ui&quot;&gt;nvim-dap-ui&lt;&#x2F;a&gt;, that adds the needed UI with variable values etc. to Neovim.
But with this setup, I faced &lt;strong&gt;several crashes&lt;&#x2F;strong&gt; of Godot and a inconsistent workflow.
So I found, in my opinion, and &lt;strong&gt;more stable&lt;&#x2F;strong&gt; and &lt;strong&gt;easier&lt;&#x2F;strong&gt; way to debug.&lt;&#x2F;p&gt;
&lt;p&gt;To be honest, the Godot&#x27;s debug UI is hard to beat, with the remote tree inspector and all the rest.
Secondly another huge problem for my game: &lt;strong&gt;launching specific scenes&lt;&#x2F;strong&gt;.
I searched the web and haven&#x27;t found a way to open a specific scene with nvim-dap.&lt;&#x2F;p&gt;
&lt;p&gt;I often run specific scenes, since my &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;99managers-futsal-edition&#x2F;&quot;&gt;latest game&lt;&#x2F;a&gt; got quite big.
Having to start from the main scene every time, can get quite &lt;strong&gt;frustrating&lt;&#x2F;strong&gt;.&lt;br &#x2F;&gt;
But you can run specific scenes from the editor, right?
Yes! But somehow Godot get&#x27;s the breakpoints set with nvim-dap, &lt;strong&gt;only&lt;&#x2F;strong&gt; when started with nvim-dap.&lt;&#x2F;p&gt;
&lt;p&gt;So I had to ask myself: how the f*ck was I debugging the last months??&lt;br &#x2F;&gt;
And well, the answer is easy, I actually was not using nvim-dap, but the &lt;strong&gt;breakpoint keyword&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The following code will print &lt;code&gt;Hello&lt;&#x2F;code&gt; and then break and wait.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _ready() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    print(&amp;quot;Hello&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    breakpoint&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    print(&amp;quot;world!&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This can have the &lt;strong&gt;disadvantages&lt;&#x2F;strong&gt; that you need to write it, and remember &lt;strong&gt;to remove it&lt;&#x2F;strong&gt;.
No worries, it won&#x27;t break your game when exported.
This keyword only works, when the project runs inside a Godot editor.&lt;&#x2F;p&gt;
&lt;p&gt;But the &lt;strong&gt;advantages&lt;&#x2F;strong&gt; are, that this breakpoints are written code, so they are persistent and can be &lt;strong&gt;shared&lt;&#x2F;strong&gt; with other developers or machines.
And there is no need for an additional Neovim plugin.&lt;&#x2F;p&gt;
&lt;p&gt;The best part of all this, I wrote my first &lt;strong&gt;custom&lt;&#x2F;strong&gt; Neovim functions&#x2F;commands (or however they are called).
Seeing for the first time, why Neovim is so fun and truly hackable.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; define functions only for Godot projects&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; is_godot_project&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; write breakpoint to new line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;GodotBreakpoint&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;normal! obreakpoint&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;write&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    end&lt;&#x2F;span&gt;&lt;span&gt;, {})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;keymap&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;leader&amp;gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:GodotBreakpoint&amp;lt;CR&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; delete all breakpoints in current file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;GodotDeleteBreakpoints&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;g&#x2F;breakpoint&#x2F;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    end&lt;&#x2F;span&gt;&lt;span&gt;, {})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;keymap&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;leader&amp;gt;BD&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:GodotDeleteBreakpoints&amp;lt;CR&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; search all breakpoints in project&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;GodotFindBreakpoints&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:grep breakpoint | copen&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    end&lt;&#x2F;span&gt;&lt;span&gt;, {})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;keymap&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;leader&amp;gt;BF&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:GodotFindBreakpoints&amp;lt;CR&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; append &amp;quot;# TRANSLATORS: &amp;quot; to current line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;GodotTranslators&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;opts&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;normal! A # TRANSLATORS: &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    end&lt;&#x2F;span&gt;&lt;span&gt;, {})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;GodotBreakpoint&lt;&#x2F;strong&gt;  adds the &quot;breakpoint&quot; String below the line the cursor is on, indented correctly.&lt;br &#x2F;&gt;
&lt;strong&gt;GodotDeleteBreakpoints&lt;&#x2F;strong&gt; deletes all breakpoints lines in the current buffer.&lt;br &#x2F;&gt;
&lt;strong&gt;GodotFindBreakpoints&lt;&#x2F;strong&gt; finds all breakpoints in the current project.
&lt;strong&gt;GodotTranslators&lt;&#x2F;strong&gt; adds a comment to the end of the line, for
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;latest&#x2F;tutorials&#x2F;i18n&#x2F;localization_using_gettext.html#extracting-localizable-strings-from-gdscript-files&quot;&gt;translation comments&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Now its possible to write, delete and search breakpoints within Neovim with simple keymaps.&lt;&#x2F;p&gt;
&lt;p&gt;Finally you need to enable also &lt;strong&gt;Debug with External Editor&lt;&#x2F;strong&gt; under the Script view.
If this flag is not set, the internal editor will open while debugging.&lt;&#x2F;p&gt;
&lt;img class=&quot;image-wide&quot; src=&quot;debug-external-editor.webp&quot; alt=&quot;Screenshot of the settings to be enabled for Debug with External Editor&quot;&gt;
&lt;h2 id=&quot;godot-documentation&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#godot-documentation&quot; aria-label=&quot;Anchor link for: godot-documentation&quot;&gt;Godot documentation&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can read documentation for a function with &lt;strong&gt;Shift + k&lt;&#x2F;strong&gt;, while the cursor is on a function.
If you want to read or search &lt;strong&gt;Godot&#x27;s full offline&lt;&#x2F;strong&gt; documentation, you can still do that in the Editor with the &lt;strong&gt;Search Help&lt;&#x2F;strong&gt; button.
This will open the documentation in Godot&#x27;s built-in editor.&lt;br &#x2F;&gt;
I don&#x27;t know if it&#x27;s even possible to open also this files in Neovim, but for me this is totally fine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;full-neovim-configuration&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#full-neovim-configuration&quot; aria-label=&quot;Anchor link for: full-neovim-configuration&quot;&gt;Full Neovim configuration&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here you can find the &lt;strong&gt;full init.lua&lt;&#x2F;strong&gt; file, ready to be hacked and extended.&lt;br &#x2F;&gt;
You can find my personal full Neovim configuration in my dofiles repo on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;dotfiles&quot;&gt;Codeberg&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;dotfiles&quot;&gt;Github&lt;&#x2F;a&gt;.
This contains some more plugins, color schemes and configurations.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ----------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; vim-plug plugin-manager&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ----------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; Plug&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fn&lt;&#x2F;span&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;plug#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;call&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;plug#begin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;nvim-treesitter&#x2F;nvim-treesitter&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, { [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;do&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;] &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:TSUpdate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Plug&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;neovim&#x2F;nvim-lspconfig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;call&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;plug#end&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ----------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; lsp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ----------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; lspconfig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;lspconfig&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;lspconfig&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;gdscript&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setup&lt;&#x2F;span&gt;&lt;span&gt;{}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ----------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; treesitter&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; -- ----------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;require&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;nvim-treesitter.configs&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setup&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    ensure_installed&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;gdscript&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;godot_resource&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;gdshader&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;},&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    highlight&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        enable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; disable auto install of languages when opening files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    auto_install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; disable for files bigger than 100 KB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    disable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;lang&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; buf&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; max_filesize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 100&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; *&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1024&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; 100 KB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        local&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ok&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; pcall&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;loop&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;fs_stat&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_buf_get_name&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;buf&lt;&#x2F;span&gt;&lt;span&gt;))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ok&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; stats&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; stats&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;size&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; max_filesize&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;            return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    end&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ----------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Godot debug config&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ----------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; write breakpoint to new line&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;GodotBreakpoint&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;normal! obreakpoint&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;write&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;, {})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;keymap&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;leader&amp;gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:GodotBreakpoint&amp;lt;CR&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; delete all breakpoints in current file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;GodotDeleteBreakpoints&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;g&#x2F;breakpoint&#x2F;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;, {})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;keymap&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;leader&amp;gt;BD&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:GodotDeleteBreakpoints&amp;lt;CR&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; search all breakpoints in project&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;api&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nvim_create_user_command&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;GodotFindBreakpoints&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:grep breakpoint | copen&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;end&lt;&#x2F;span&gt;&lt;span&gt;, {})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span&gt;keymap&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;set&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;lt;leader&amp;gt;BF&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;:GodotFindBreakpoints&amp;lt;CR&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;ignore-some-files&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ignore-some-files&quot; aria-label=&quot;Anchor link for: ignore-some-files&quot;&gt;Ignore some files&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you use file explorers plugins you might want to hide some files for Godot projects.
Like the server.pipe file or all *.uid files introduced in Godot 4.4.&lt;br &#x2F;&gt;
This hides the files in &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;preservim&#x2F;nerdtree&quot;&gt;Nerdtree&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; is_godot_project&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ignore *.uid files introduced in godot 4.4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ignore server.pipe file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cmd&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;let NERDTreeIgnore = [&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;\\&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.uid$&amp;quot;, &amp;quot;server.pipe&amp;quot;]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And this &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;stevearc&#x2F;oil.nvim&quot;&gt;Oil&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;lua&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ----------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; oil&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;--&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ----------------------&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;require&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;oil&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt;).&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;setup&lt;&#x2F;span&gt;&lt;span&gt;({&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    view_options&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        show_hidden&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        is_always_hidden&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; =&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; function&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;name&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;span&gt; bufnr&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;            --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; for godot projects ignore *.uid files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;            if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; is_godot_project&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;                --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ignore *.uid files introduced in godot 4.4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;                if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; vim&lt;&#x2F;span&gt;&lt;span&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;endswith&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span&gt;, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.uid&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;                    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;                end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;                --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; ignore server.pipe file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;                if&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; ==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;server.pipe&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39; &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;                    return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;                end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;            else&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;                return&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;            end&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        end&lt;&#x2F;span&gt;&lt;span&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    },&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;})&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you use other file explorer plugins, there surely is a way to hide this files too.
Just check the docs or some example configs.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-i-miss-in-neovim&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-i-miss-in-neovim&quot; aria-label=&quot;Anchor link for: what-i-miss-in-neovim&quot;&gt;What I miss in Neovim&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So far the biggest feature I miss, is the easy &lt;strong&gt;Ctrl + drag and drop&lt;&#x2F;strong&gt; of a Node into the text editor.
This will automatically create the var with the correct Nodepath.&lt;&#x2F;p&gt;
&lt;p&gt;After some time I found a much better approach by using &lt;strong&gt;%&lt;&#x2F;strong&gt; and
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;scripting&#x2F;scene_unique_nodes.html#creation-and-usage&quot;&gt;&lt;strong&gt;Access as Unique Name&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;.
With this you can access the Node, without having to write the full Node path.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# This long path&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@onready var healt_label: Label = $MarginContainer&#x2F;HBoxContainer&#x2F;VBoxContainer&#x2F;HealthLabel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# simply becomes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@onready var healt_label: Label = %HealthLabel&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Another crucial advantage is that you can move the Node around the tree, or change parent Nodes, without having to adjust the path.&lt;&#x2F;p&gt;
&lt;p&gt;At the end of the day, being able to use Neovim pays back anyways, if you like it and are keen to keep learning.
Or you already know everything about Vim&#x2F;Neovim, but let&#x27;s be honest, &lt;strong&gt;nobody does&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;credits&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#credits&quot; aria-label=&quot;Anchor link for: credits&quot;&gt;Credits&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I want to thank &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;DanWlker&quot;&gt;Daniel&lt;&#x2F;a&gt; for his great suggestions.
Now multiple instances can be used and the server mode only starts, if a Godot project has been found.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Having fun with Godot Movie Maker - Part 1</title>
          <pubDate>Tue, 17 Dec 2024 17:26:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-moviemaker-part1/</link>
          <guid>https://simondalvai.org/blog/godot-moviemaker-part1/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-moviemaker-part1/">&lt;p&gt;To release a game on Steam, it is good to have &lt;strong&gt;at least one video trailer&lt;&#x2F;strong&gt; about the game.
For releasing only the store page, it doesn&#x27;t really need to be a video about actual game play.
It can only be a teaser, where you announce your game.&lt;&#x2F;p&gt;
&lt;p&gt;I don&#x27;t have much experience with video creation and editing, so I started to &lt;strong&gt;search the web&lt;&#x2F;strong&gt; once again for Open Source video editing tools.
The first I found where &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.openshot.org&#x2F;&quot;&gt;OpenShot&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;kdenlive.org&quot;&gt;Kdenlive&lt;&#x2F;a&gt; or directly &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.ffmpeg.org&#x2F;&quot;&gt;FFmpeg&lt;&#x2F;a&gt;,
which I know from the past.
But I used them mostly to cut or modify existing videos, not to create new content from scratch.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godot-movie-maker-to-the-rescue&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#godot-movie-maker-to-the-rescue&quot; aria-label=&quot;Anchor link for: godot-movie-maker-to-the-rescue&quot;&gt;Godot Movie Maker to the rescue!&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;After some time, I remembered that Godot actually has a feature called &lt;strong&gt;Movie Maker&lt;&#x2F;strong&gt;.
And the best part is:&lt;br &#x2F;&gt;
I know how to use Godot &lt;strong&gt;+&lt;&#x2F;strong&gt; it can make movies &lt;strong&gt;= perfect match!&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Godot&#x27;s Movie Maker feature allows you to create Movies with everything Godot is capable of.
So you can code a movie using &lt;strong&gt;Tweens&lt;&#x2F;strong&gt;, the &lt;strong&gt;AnimationPlayer&lt;&#x2F;strong&gt;, pure &lt;strong&gt;code&lt;&#x2F;strong&gt; or whatever comes to your mind.&lt;br &#x2F;&gt;
The best part is, everything is &lt;strong&gt;automated&lt;&#x2F;strong&gt; and supports versioning with &lt;strong&gt;git&lt;&#x2F;strong&gt;.
So for example it&#x27;s possible to &lt;strong&gt;translate&lt;&#x2F;strong&gt; the video in different languages with ease.
Or if you made a mistake and broke something, simply run &lt;strong&gt;git restore&lt;&#x2F;strong&gt; and your work is save.&lt;&#x2F;p&gt;
&lt;img class=&quot;image&quot; src=&quot;magic-button.webp&quot; alt=&quot;A screenshot of Godot&#x27;s Movie Maker button&quot;&gt;
&lt;p&gt;Here you can see the &lt;strong&gt;magic button&lt;&#x2F;strong&gt;, that transforms Godot into Hollywood.
Just press it and when you run a scene or the game, everything visible on the screen will be saved to a file.
The file needs to be defined under &lt;strong&gt;Project Settings&amp;gt;Editor&amp;gt;Movie Writer&amp;gt;Movie File&lt;&#x2F;strong&gt;.
Or add the String &lt;strong&gt;move_file&lt;&#x2F;strong&gt; to the scene&#x27;s &lt;strong&gt;metadata&lt;&#x2F;strong&gt; as I did in the screenshot below.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;metadata.webp&quot; alt=&quot;A screenshot movie_file metadata place in the inspector&quot;&gt;
&lt;p&gt;If you plan to only make one video with your project, use the project settings.
Otherwise the metadata is more convenient, because you can have multiple files defined for different scenes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-first-result&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-first-result&quot; aria-label=&quot;Anchor link for: the-first-result&quot;&gt;The first result&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This is my very first video created with Godot. Oscars, I&#x27;m coming!&lt;br &#x2F;&gt;
You can find it on
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;3334770&#x2F;99Managers_Futsal_Edition&#x2F;&quot;&gt;Steam&lt;&#x2F;a&gt;,
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=ToVRZsfPimE&quot;&gt;YouTube&lt;&#x2F;a&gt;
or if you prefer, &lt;strong&gt;more privacy friendly&lt;&#x2F;strong&gt; on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@dulvui&#x2F;113628533674230281&quot;&gt;Mastodon&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;It&#x27;s quite simple with no special effects, except the ball fireworks at the end.
But I was quite &lt;strong&gt;fast&lt;&#x2F;strong&gt; to create it and I was able to &lt;strong&gt;iterate&lt;&#x2F;strong&gt;, like I do with while programming.
I can only guess how much effort it would have been, to create it with some other video editing tool.&lt;&#x2F;p&gt;
&lt;p&gt;Below the few lines of code needed for this simple trailer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Control&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@onready var animation_player: AnimationPlayer = %AnimationPlayer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _ready() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	theme = ThemeUtil.get_active_theme()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	animation_player.play(&amp;quot;Teaser&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As you an see, the real work is done by the &lt;strong&gt;AnimationPlayer&lt;&#x2F;strong&gt;.
For someone who doesn&#x27;t know Godot, the AnimationPlayer can &lt;strong&gt;change the properties over time&lt;&#x2F;strong&gt;.&lt;br &#x2F;&gt;
Like in the screenshot below, I can simply make text labels &lt;strong&gt;fade in and out&lt;&#x2F;strong&gt;,
or trigger the CPUParticles, that are the final ball fireworks effect.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;animation-player.webp&quot; alt=&quot;A screenshot of the AnimationPlayer configuration&quot;&gt;
&lt;p&gt;For the first attempt this was totally fine, but it needs a &lt;strong&gt;lot of clicking, sliding and patience&lt;&#x2F;strong&gt;.
I highly prefer to code everything and use less the mouse.
But this will be covered in a future part 2 of this blog post.&lt;&#x2F;p&gt;
&lt;p&gt;You can find the full source code
on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;99managers-futsal-edition&#x2F;src&#x2F;branch&#x2F;main&#x2F;game&#x2F;src&#x2F;media&quot;&gt;Codeberg&lt;&#x2F;a&gt;
or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;99managers-futsal-edition&#x2F;tree&#x2F;main&#x2F;game&#x2F;src&#x2F;media&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
Note: The location of the trailer files might change in the future, so this links might break.
Let me know if that happens, so I can fix it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;performance&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#performance&quot; aria-label=&quot;Anchor link for: performance&quot;&gt;Performance&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Video editing and gaming (in a world before LLMs) are the most resource intensive tasks you probably can do on a computer.
Godot isn&#x27;t much different, but I have to say that &lt;strong&gt;it worked quite well&lt;&#x2F;strong&gt; on my potato laptop (dual core i5 7th gen, no GPU).
You can see the output directly while it is written to the file, and it &lt;strong&gt;takes about 2x more&lt;&#x2F;strong&gt; time.
So for a video of 10 seconds like mine, the recording takes about 20 seconds.
But I can imagine that a proper computer, should be able to play and write the videos &lt;strong&gt;at normal speed&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-will-be-in-part-2&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-will-be-in-part-2&quot; aria-label=&quot;Anchor link for: what-will-be-in-part-2&quot;&gt;What will be in part 2?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I actually wanted to fit also the second game play trailer in this blog post.
But I want to make it really good, to attract the most people possible with it.
For that reason, I still need some time to improve the game itself.&lt;br &#x2F;&gt;
But I can already anticipate that Godot&#x27;s Movie Maker is &lt;strong&gt;really powerful&lt;&#x2F;strong&gt;.
I was able to use actual game scenes for the videos and even &lt;strong&gt;interact&lt;&#x2F;strong&gt; with them, while recording.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-thoughts&quot; aria-label=&quot;Anchor link for: final-thoughts&quot;&gt;Final thoughts&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The Godot Movie Maker is much better as expected and makes the video making really fun.
It is incredible, how &lt;strong&gt;simple but yet powerful&lt;&#x2F;strong&gt; this feature is.&lt;br &#x2F;&gt;
I could imagine making videos also for non gaming stuff, where things like text or effects can be automated.&lt;br &#x2F;&gt;
Now I just need to add the Godot Engine to all the FOSS video creation tools list on the web ;-)
So the next one who searches the web, finds this hidden gem.&lt;br &#x2F;&gt;
Last but not least, the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;godotengine.org&#x2F;article&#x2F;movie-maker-mode-arrives-in-godot-4&#x2F;&quot;&gt;official release note&lt;&#x2F;a&gt; of the Godot Movie Maker,
if you want to know more about it.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Debian Sway v1 - My first setup</title>
          <pubDate>Sat, 16 Nov 2024 10:15:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/debian-sway-v1/</link>
          <guid>https://simondalvai.org/blog/debian-sway-v1/</guid>
          <description xml:base="https://simondalvai.org/blog/debian-sway-v1/">&lt;p&gt;This year I started using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;swaywm.org&#x2F;&quot;&gt;Sway&lt;&#x2F;a&gt; on my laptop running the latest stable &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.debian.org&#x2F;&quot;&gt;Debian 12&lt;&#x2F;a&gt;.
Sway is a tiling window manager and a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;i3wm.org&#x2F;&quot;&gt;i3wm&lt;&#x2F;a&gt; clone for Wayland.
As all tiling window managers, you can start, arrange and align windows directly &lt;strong&gt;with the keyboard&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;debian-sway.webp&quot; alt=&quot;A screenshot of my Debain Sway setup with a Debian logo on a blue background with a moon in the center.&quot;&gt;  
&lt;p&gt;I didn&#x27;t find much on the web about how to setup Sway on Debian, therefore I will share my experience here.
Getting it running on Debian needs &lt;strong&gt;time and patience&lt;&#x2F;strong&gt;.
There is no official or unofficial Debian ISO image and that means you need to setup everything from scratch.&lt;&#x2F;p&gt;
&lt;p&gt;If you simply want to try Sway, without having to setup everything on your own, I would suggest &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fedoraproject.org&#x2F;spins&#x2F;sway&#x2F;&quot;&gt;Fedora Sway&lt;&#x2F;a&gt;.
It has a lot of tools already installed out of the box and is a great place to get a first impression.&lt;&#x2F;p&gt;
&lt;p&gt;As for every &lt;strong&gt;highly configurable system&lt;&#x2F;strong&gt;, no configuration is the same and everybody needs to &lt;strong&gt;find what fits&lt;&#x2F;strong&gt; best.
Keep in mind that this is no tutorial with exact and precise needed steps, but more a direction sign, showing you a possible path.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;xfce-kde-and-workspaces&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#xfce-kde-and-workspaces&quot; aria-label=&quot;Anchor link for: xfce-kde-and-workspaces&quot;&gt;XFCE, KDE and workspaces&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As you might saw in my previous &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;vscode-to-neovim&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt;, this year I also started using Neovim.
At that time, I was still using KDE Plasma 5 and I loved it.
I used a 3x3 workspace grid, I brought over from XFCE and had specific programs always in the same workspace.&lt;&#x2F;p&gt;
&lt;p&gt;But being able to do everything with a few keystrokes, like in Neovim, just feels so nice.
Then I finally tried Sway, &lt;strong&gt;side by side&lt;&#x2F;strong&gt; to KDE Plasma and used both for some time.&lt;br &#x2F;&gt;
You can do that easily on Debian (and surely also on other distros), by simply installing Sway and then choosing it as desktop environment on the login screen.
Not everything was working 100%, but at least I got an idea if I like Sway or not.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;all-or-nothing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#all-or-nothing&quot; aria-label=&quot;Anchor link for: all-or-nothing&quot;&gt;All or nothing&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;After a few weeks of using this hybrid system, I actually &lt;strong&gt;uninstalled Sway&lt;&#x2F;strong&gt; again and went back to KDE Plasma.
I simply couldn&#x27;t get used to the Sway way of doing things and missed the ease of my old setup.&lt;&#x2F;p&gt;
&lt;p&gt;But in my opinion, with tools that need (a lot of) &lt;strong&gt;time and muscle memory&lt;&#x2F;strong&gt; to master, like Vim and Sway, you need to &lt;strong&gt;go all in&lt;&#x2F;strong&gt;.
If you simply can switch to your old editor or desktop environment, you will never learn it for real.
In difficult moments, you will simply switch to the other one, but exactly in that moments, you&#x27;ll &lt;strong&gt;learn the most&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Then I finally did the hard switch and reinstalled Debian without any desktop environment and installed Sway on top of it.
Now I can&#x27;t imagine using a &quot;conventional&quot; desktop environment again.&lt;br &#x2F;&gt;
Tiling window managers can give you a &lt;strong&gt;feeling of connection&lt;&#x2F;strong&gt; to your machine, that no mouse drag and click can replace.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-good-and-the-better&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-good-and-the-better&quot; aria-label=&quot;Anchor link for: the-good-and-the-better&quot;&gt;The good and the better&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now here I am, with a minimalistic Debian install and Sway, but nothing else.&lt;br &#x2F;&gt;
But, how can I connect to my WiFi?
Does Bluetooth work?
What did just happen?! Ohh, the battery is empty.&lt;br &#x2F;&gt;
This and other stories will happen, the &lt;strong&gt;first time&lt;&#x2F;strong&gt; you&#x27;ll use such a bare bones setup.
In my previous try, all this things where covered by KDE, but Sway doesn&#x27;t come with batteries included.
The Debian setup without desktop environment is &lt;strong&gt;designed for servers&lt;&#x2F;strong&gt; and they don&#x27;t have displays, batteries or Bluetooth.&lt;&#x2F;p&gt;
&lt;p&gt;This can be seen as bad, but in some way also as good, right?
You&#x27;ll learn a lot of new tools and see &lt;strong&gt;under the hood&lt;&#x2F;strong&gt; of a conventional desktop environment.
All the heavy lifting a desktop environment does, is now on you.&lt;&#x2F;p&gt;
&lt;p&gt;I spent hours and hours trying to understand, which cli&#x2F;GUI tool can cover my needs.
And now I have a nearly perfect setup and can do everything with the keyboard.
I couldn&#x27;t imagine using something else.&lt;br &#x2F;&gt;
To note, that I exactly thought the same for XFCE then KDE ;-)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-killer-feature&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-killer-feature&quot; aria-label=&quot;Anchor link for: the-killer-feature&quot;&gt;The killer feature&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;But in my opinion the &lt;strong&gt;real killer feature&lt;&#x2F;strong&gt; of Sway is that it&#x27;s reproducible.
Every tool and Sway itself, has it&#x27;s own config file, that can be versioned and restored with git.
With that, you no longer have to remember what checkbox you clicked in the settings GUI.
If you reinstall your OS or change distro, you can simply &lt;strong&gt;bring your config&lt;&#x2F;strong&gt; files with you.&lt;&#x2F;p&gt;
&lt;p&gt;You can even &lt;strong&gt;synchronize&lt;&#x2F;strong&gt; everything automatically with other machines.
For example, you change your Sway key binds at home and the next day at work, get the changes instantly synced to your working machine.
I currently use a git and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;syncthing.net&#x2F;&quot;&gt;Syncthing&lt;&#x2F;a&gt; combination to backup and synchronize my most precious files.
Even on my Android phone with Neovim on Termux, I was able to reuse my Neovim configuration
(this was just an experiment, I&#x27;m not that crazy, yet...).
I guess, someday this synchronization setup will get it&#x27;s own blog post.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tools&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tools&quot; aria-label=&quot;Anchor link for: tools&quot;&gt;Tools&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To save you some time, I tried to list all important tools I&#x27;m using.&lt;br &#x2F;&gt;
You can see my configuration of the following tools and my Debian install.sh script in my dotfiles repo on
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;dotfiles&quot;&gt;Codeberg&lt;&#x2F;a&gt;
or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;dotfiles&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;terminal&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#terminal&quot; aria-label=&quot;Anchor link for: terminal&quot;&gt;Terminal&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;A fast, lightweight and minimalist Wayland terminal emulator aka &lt;strong&gt;foot&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; foot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can even start it in server mode to save memory, not that it uses much, but still cool!
For me it was enough, being able to install a solarized-light theme easily.
When choosing the terminal, you should just make sure that your terminal emulator of choice &lt;strong&gt;supports Wayland&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;A good alternative is &lt;strong&gt;Alacritty&lt;&#x2F;strong&gt;.
But the version on Debian (at the time of writing) doesn&#x27;t have yet the new toml configuration file.
Therefore, a lot of guides didn&#x27;t work.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;neovim&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#neovim&quot; aria-label=&quot;Anchor link for: neovim&quot;&gt;Neovim&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Well, you probably already use &lt;strong&gt;Neovim&lt;&#x2F;strong&gt; or another terminal based editor, if you feel the need to use Sway.
Or maybe it will happen vice versa, using Sway will make you switch to one.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; neovim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will install a quite &quot;old&quot; version of Neovim.
If you just want to use Neovim without much plugins, this version is fine for you.
But the &lt;strong&gt;more plugins&lt;&#x2F;strong&gt; you use, the &lt;strong&gt;more compatibility issues&lt;&#x2F;strong&gt; you&#x27;ll face.
Read in my previous &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;vscode-to-neovim&#x2F;#getting-the-latest-version-on-debian&quot;&gt;blog post&lt;&#x2F;a&gt;, on how to get the latest version to Debian 12.&lt;&#x2F;p&gt;
&lt;p&gt;Most famous &lt;del&gt;enemy&lt;&#x2F;del&gt; alternative is of course &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.gnu.org&#x2F;software&#x2F;emacs&#x2F;&quot;&gt;GNU Emacs&lt;&#x2F;a&gt; ;-)&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;debian-sway-vim.webp&quot; alt=&quot;A screenshot of three open terminals running with one running Neovim.&quot;&gt;  
&lt;p&gt;Beautiful, beautiful Neovim with solarized-light theme (on the left).&lt;&#x2F;p&gt;
&lt;h3 id=&quot;terminal-multiplexer&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#terminal-multiplexer&quot; aria-label=&quot;Anchor link for: terminal-multiplexer&quot;&gt;Terminal multiplexer&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;When you live in the terminal, having something like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tmux&#x2F;tmux&quot;&gt;tmux&lt;&#x2F;a&gt; is a great help.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; tmux&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It brings multiple and detachable sessions, vertical and horizontal splitting, session recovery and much more.
I haven&#x27;t figured it all out yet.&lt;&#x2F;p&gt;
&lt;p&gt;I use it daily and combined with Sway, it is really great.
In my setup, when opening a terminal, a tmux session will always start automatically.
Tmux is not essential and can be too much overhead, if you still need to learn and setup Sway.
My recommendation is, once you feel confident with Sway, try tmux.&lt;&#x2F;p&gt;
&lt;p&gt;An older and simpler alternative can be &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;savannah.gnu.org&#x2F;projects&#x2F;screen&quot;&gt;screen&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;network-manager&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#network-manager&quot; aria-label=&quot;Anchor link for: network-manager&quot;&gt;Network Manager&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Remember clicking in your system tray and choose the WiFi in a nice looking UI?
This days are over and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.gnome.org&#x2F;Projects&#x2F;NetworkManager&quot;&gt;Gnome&#x27;s Network Manager&lt;&#x2F;a&gt; will make it easy to never look back.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; network-manager&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once installed you can simply run &lt;strong&gt;nmtui&lt;&#x2F;strong&gt; and you&#x27;ll see a terminal user interface with all needed networks settings.
In my opinion it looks quite cool, but if you don&#x27;t agree, there surely exists another network manager with a nice GUI.&lt;&#x2F;p&gt;
&lt;p&gt;This is the only terminal network manager tool I found on Debian.
Other distros like Arch, have a lot of more options.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;battery-optimizations&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#battery-optimizations&quot; aria-label=&quot;Anchor link for: battery-optimizations&quot;&gt;Battery optimizations&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The best tool I found in general for battery optimization, is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;linrunner.de&#x2F;tlp&#x2F;&quot;&gt;TLP&lt;&#x2F;a&gt;.
It allows you also to limit the charging to 80%, for a increased total battery lifetime.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; tlp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; start it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;tlp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; start&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I used it also on other distros with various desktop environments and it always worked great.
I brings a lot of features like turning on bluetooth&#x2F;wifi from cli.
For that, simply type &lt;strong&gt;bluetooth on&lt;&#x2F;strong&gt; and &lt;strong&gt;wifi off&lt;&#x2F;strong&gt;.
Or you can also disable them automatically on boot in the tlp config file.&lt;&#x2F;p&gt;
&lt;p&gt;A terrible battery experience I had, was the unexpected power off, when the &lt;strong&gt;battery was empty&lt;&#x2F;strong&gt;.
I highly prefer to suspend on 5% of battery, so I have time to find a charger.&lt;br &#x2F;&gt;
You achieve that, by creating a new udev rule under &lt;strong&gt;&#x2F;etc&#x2F;udev&#x2F;rules.d&#x2F;99-lowbat.rules&lt;&#x2F;strong&gt; with the following content.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Suspend the system on 5% or lower&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;SUBSYSTEM&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;power_supply&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; ATTR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;{&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;}&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Discharging&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; ATTR{capacity}==&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;[0-5]&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; RUN+=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;systemctl suspend&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now you are save and your system will not self destroy itself unexpectedly.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;sway-bar&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#sway-bar&quot; aria-label=&quot;Anchor link for: sway-bar&quot;&gt;Sway bar&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Sway comes with that tiny bar on the top or bottom, where you can see your workspaces, the time and any other info you need.&lt;br &#x2F;&gt;
Personally I use the built-in sway-bar, but many prefer and use the more feature packed &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Alexays&#x2F;Waybar&quot;&gt;Waybar&lt;&#x2F;a&gt;.
The Waybar can adjust volume, back light by &lt;strong&gt;mouse scroll&lt;&#x2F;strong&gt; or shutdown you machine with some mouse clicks.&lt;br &#x2F;&gt;
Another gem I found is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dnkl&#x2F;yambar&quot;&gt;yambar&lt;&#x2F;a&gt; from the foot terminal author.
Looks great and is similar to Waybar.&lt;&#x2F;p&gt;
&lt;p&gt;I recommend &lt;strong&gt;to try all&lt;&#x2F;strong&gt; out and find what covers your needs best.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;multiple-monitors&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#multiple-monitors&quot; aria-label=&quot;Anchor link for: multiple-monitors&quot;&gt;Multiple monitors&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;packages.debian.org&#x2F;bookworm&#x2F;kanshi&quot;&gt;Kanshi&lt;&#x2F;a&gt; is a really useful tool, if you use a laptop that will connect to other monitors.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; kanshi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It allows you to define a monitor&#x27;s position, resolution, orientation and much more.
So you can for example &lt;strong&gt;disable the laptop&#x27;s display&lt;&#x2F;strong&gt; while attached to other monitors.
Or simply define which workspace is on which monitor.&lt;&#x2F;p&gt;
&lt;p&gt;I still have some minor issues, that sometimes it doesn&#x27;t really change workspace arrangement when docking my laptop.
Anyway, when reloading the Sway config with &lt;strong&gt;Ctrl + c&lt;&#x2F;strong&gt;, it&#x27;s fixed 9 out of 10 times.
If not, I simply reload, until its fixed.
I suspect that there is some race condition, with another component of Sway.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;more-tools&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#more-tools&quot; aria-label=&quot;Anchor link for: more-tools&quot;&gt;More tools...&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Here some more tools I&#x27;m currently using.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.xfce.org&#x2F;xfce&#x2F;thunar&#x2F;start&quot;&gt;&lt;strong&gt;thunar&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; - fast and lightweight file manager&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;hg.sr.ht&#x2F;~scoopta&#x2F;wofi&quot;&gt;&lt;strong&gt;wofi&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; - application launcher and menu&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;sr.ht&#x2F;~kennylevinsen&#x2F;wlsunset&#x2F;&quot;&gt;&lt;strong&gt;wlsunset&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; - blue light filter&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;emersion&#x2F;mako&quot;&gt;&lt;strong&gt;mako&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; - lighweight notification daemon&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;emersion&#x2F;slurp&#x2F;releases&quot;&gt;&lt;strong&gt;slurp&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;packages.debian.org&#x2F;bookworm&#x2F;grimshot&quot;&gt;&lt;strong&gt;grimshot&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; - screenshots&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;GeorgeFilipkin&#x2F;pulsemixer&quot;&gt;&lt;strong&gt;pulsemixer&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; - cli audio control&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dvorka&#x2F;hstr&quot;&gt;&lt;strong&gt;hstr&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; - see and search your full bash history with Ctrl + r&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;packages.debian.org&#x2F;bookworm&#x2F;xwayland&quot;&gt;&lt;strong&gt;xwayland&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; - run X clients on Wayland&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;packages.debian.org&#x2F;bookworm&#x2F;light&quot;&gt;&lt;strong&gt;light&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt; - adjust display brightness&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And here the last screenshot, running &lt;strong&gt;hstr&lt;&#x2F;strong&gt; (bottom left), &lt;strong&gt;pulsemixer&lt;&#x2F;strong&gt; (top left) and &lt;strong&gt;nmtui&lt;&#x2F;strong&gt; (right).&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;debian-sway-tools.webp&quot; alt=&quot;A screenshot of three open terminals with hstr, nmtui and pulsemixer&quot;&gt;  
&lt;h2 id=&quot;fine-tuning&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#fine-tuning&quot; aria-label=&quot;Anchor link for: fine-tuning&quot;&gt;Fine tuning&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I did some other minor changes to fit my needs and habits.
I tried and changed a lot of stuff, but I hope I covered everything in my dotfiles repo and here in this blog post.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;grant-some-permissions&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#grant-some-permissions&quot; aria-label=&quot;Anchor link for: grant-some-permissions&quot;&gt;Grant some permissions&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I like having my user &lt;strong&gt;not in the sudoers group&lt;&#x2F;strong&gt;, like Debian has per default.
Because of that, I can&#x27;t simply run &lt;strong&gt;sudo command&lt;&#x2F;strong&gt; but have to use the root user.&lt;br &#x2F;&gt;
I really like this approach, since I know when I use root, to &lt;strong&gt;be cautious&lt;&#x2F;strong&gt;.
And secondly, no shady script (or more probably myself) can run &lt;strong&gt;dangerous&lt;&#x2F;strong&gt; sudo commands with my user.&lt;br &#x2F;&gt;
The only drawback is that some programs like &lt;strong&gt;light&lt;&#x2F;strong&gt; or &lt;strong&gt;systemctl&lt;&#x2F;strong&gt; need root access.
So I granted root access to my user for that programs, by running the following 2 lines, as root user.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;# for light and systemctl shutdown, suspend, reboot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &#x2F;etc&#x2F;sudoers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;%dulvui ALL=(root) NOPASSWD: &#x2F;usr&#x2F;bin&#x2F;light,&#x2F;usr&#x2F;bin&#x2F;systemctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &#x2F;etc&#x2F;sudoers&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now I can change my laptops display brightness.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; more bright&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;light&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; less bright&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;light&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;U&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And use systemctl for even more trivial things, without sudo.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; poweroff&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; suspend&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; reboot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;power-button-instant-shutdown&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#power-button-instant-shutdown&quot; aria-label=&quot;Anchor link for: power-button-instant-shutdown&quot;&gt;Power button instant shutdown&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Per default, your machine will power off instantly, when you press the power button.
This can get annoying, when you &lt;strong&gt;intend to wake up&lt;&#x2F;strong&gt; your machine from suspension and instead &lt;strong&gt;turn it off&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Thanks to this &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;swaywm&#x2F;comments&#x2F;180ly44&#x2F;how_to_change_power_button_behavior&#x2F;&quot;&gt;reddit post&lt;&#x2F;a&gt;,
I found the solution.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; as root&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;vim&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &#x2F;etc&#x2F;systemd&#x2F;logind.conf&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; change following values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;HandlePowerKey&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;HandlePowerKeyLongPress&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;f&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; restart logind or reboot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;systemctl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; restart&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; systemd-logind&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The long press power button (emergency) shutdown still works, because &lt;strong&gt;HandlePowerKeyLongPress&lt;&#x2F;strong&gt; is set to poweroff.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;bluetooth-audio&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#bluetooth-audio&quot; aria-label=&quot;Anchor link for: bluetooth-audio&quot;&gt;Bluetooth audio&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Getting my wireless headphones to &lt;strong&gt;connect&lt;&#x2F;strong&gt; and play &lt;strong&gt;good quality sound&lt;&#x2F;strong&gt;, was maybe the most difficult problem I solved, somehow...&lt;br &#x2F;&gt;
First, I was able to connect them, but the quality was really bad (using Hands Free protocol).
Now it is working fine, but for this I changed so much, that I can&#x27;t really tell, what worked in the end.&lt;br &#x2F;&gt;
I will try my best and list what I have installed, to fix the issue (out of frustration).&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; audio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pipewire&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; wireplumber&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pipewire-alsa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pipewire-audio&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pipewire-audio-client-libraries&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pipewire-bin&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pipewire-jack&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pipewire-pulse&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; bluetooth&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; bluez&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; gui for pairing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; blueman&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; for a2dp and other bluetooth profiles&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; libspa-0.2-bluetooth&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Once I install my OS again, I will be able to test what actually fixed the issue.
Then I will update also this blog post.
Until then, if you tested it or simply know it better, &lt;strong&gt;please contact me&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Note: I own Sony headphones and I need to mention this, since it seems that many companies have their &lt;strong&gt;own Bluetooth profile&lt;&#x2F;strong&gt;.
For that reason, it could be that yours work out of the box or need another library to work.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;start-sway-on-login&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#start-sway-on-login&quot; aria-label=&quot;Anchor link for: start-sway-on-login&quot;&gt;Start Sway on login&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Simply put the following lines to your &lt;strong&gt;~&#x2F;.profile&lt;&#x2F;strong&gt; file and Sway will launch automatically, once you logged in.
This will also set some Wayland flags for Firefox, Thunderbird and other applications.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Sway autostart&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;if&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;WAYLAND_DISPLAY&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span&gt; [&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;XDG_VTNR&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; -eq&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 1&lt;&#x2F;span&gt;&lt;span&gt; ]&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; then&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; MOZ_ENABLE_WAYLAND&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt;1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; XDG_SESSION_TYPE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;wayland&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#586E75, #93A1A1);font-weight: bold;&quot;&gt;    export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; XDG_CURRENT_DESKTOP&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;sway&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    exec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; sway&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;fi&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;I tried some login screens with nice GUIs, but at the end I use the default &quot;login:&quot; white text on black background.
Simple yet effective and once I got used to it, I didn&#x27;t mind that it doesn&#x27;t look fancy.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;screen-sharing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#screen-sharing&quot; aria-label=&quot;Anchor link for: screen-sharing&quot;&gt;Screen sharing&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;This was the main reason, I still kept KDE on my system, since it &lt;strong&gt;didn&#x27;t work&lt;&#x2F;strong&gt; out of the box with Sway.
But then I decided to bite the bullet and finally fixed it thanks to this guide on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.reddit.com&#x2F;r&#x2F;swaywm&#x2F;comments&#x2F;l4e55v&#x2F;guide_how_to_screenshare_from_chromiumfirefox&#x2F;&quot;&gt;Reddit&lt;&#x2F;a&gt;
This was the final hurdle I had to pass, before switching fully to Sway.&lt;br &#x2F;&gt;
To get it working, simply install the following programs.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; xdg-desktop-portal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; xdg-desktop-portal-wlr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Append the following lines to your Sway config file, or somewhere that will execute them, after Wayland has started.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;exec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &#x2F;usr&#x2F;libexec&#x2F;xdg-desktop-portal&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;r&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;exec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &#x2F;usr&#x2F;libexec&#x2F;xdg-desktop-portal-wlr&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And make sure the flag &lt;strong&gt;MOZ_ENABLE_WAYLAND=1&lt;&#x2F;strong&gt; from the previous section is set.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;future-improvements-aka-v2&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#future-improvements-aka-v2&quot; aria-label=&quot;Anchor link for: future-improvements-aka-v2&quot;&gt;Future improvements aka v2&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;As you can imagine, after reading the title of this blog post, there will be a v2.&lt;&#x2F;p&gt;
&lt;p&gt;I could imagine &lt;strong&gt;replacing my bash scripts&lt;&#x2F;strong&gt;, with something more mature and reliable as &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.ansible.com&#x2F;&quot;&gt;Ansible&lt;&#x2F;a&gt;.
This would make the setup reproducible for everyone and more portable, maybe even for other distros.
If I switch to Ansible, I&#x27;ll let you know for sure, in another blog post.&lt;br &#x2F;&gt;
Then I will discover more cool tools, or even &lt;strong&gt;switch to Arch&lt;&#x2F;strong&gt;?
Or simply upgrade to Debian 13 Trixie and save some years of life and gray hair.&lt;&#x2F;p&gt;
&lt;p&gt;Last but not least, v3 will be my own Debian distribution with Sway, maybe &lt;strong&gt;Swaybian&lt;&#x2F;strong&gt;?
Or I could become the maintainer of an official Debian Sway release.
Never stop dreaming :-)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;useful-links&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#useful-links&quot; aria-label=&quot;Anchor link for: useful-links&quot;&gt;Useful links&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To conclude my &lt;strong&gt;longest blog post so far&lt;&#x2F;strong&gt;, a collection of links and wikis I found useful on my journey.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Sway page on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.archlinux.org&#x2F;title&#x2F;Sway&quot;&gt;ArchWiki&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Sway page on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.gentoo.org&#x2F;wiki&#x2F;Sway&quot;&gt;Gentoo Wiki&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Sway page on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.debian.org&#x2F;sway&quot;&gt;Debian Wiki&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Fedora Sway &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;fedora&#x2F;sigs&#x2F;sway&#x2F;sway-config-fedora&quot;&gt;config repo&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;Bluetooth page on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.debian.org&#x2F;BluetoothUser&quot;&gt;Debian wiki&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Note: The ArchWiki was especially helpful in general.
You can find a lot of great cli tools and information, about how to run a minimalist OS.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>From VSCode&#x2F;VSCodium to Neovim</title>
          <pubDate>Fri, 18 Oct 2024 21:58:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/vscode-to-neovim/</link>
          <guid>https://simondalvai.org/blog/vscode-to-neovim/</guid>
          <description xml:base="https://simondalvai.org/blog/vscode-to-neovim/">&lt;p&gt;I was using &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;code.visualstudio.com&#x2F;&quot;&gt;VSCode&lt;&#x2F;a&gt; and later &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;vscodium.com&#x2F;&quot;&gt;VSCodium&lt;&#x2F;a&gt; for some years as my editor for everything.
They are &lt;strong&gt;awesome tools&lt;&#x2F;strong&gt; and are getting the job done.
But as you might know, VSCode is built by Microsoft, and has in my opinion &lt;strong&gt;some issues&lt;&#x2F;strong&gt;,
like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;VSCodium&#x2F;vscodium&#x2F;blob&#x2F;master&#x2F;docs&#x2F;index.md#getting-all-the-telemetry-out&quot;&gt;telemetry&lt;&#x2F;a&gt;,
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;VSCodium&#x2F;vscodium&#x2F;blob&#x2F;master&#x2F;docs&#x2F;index.md#extensions--marketplace&quot;&gt;proprietary extensions ecosystem&lt;&#x2F;a&gt;
and actually &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;VSCodium&#x2F;vscodium?tab=readme-ov-file#why&quot;&gt;not being FOSS&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I think Microsoft did really a great job here and VSCode is a great tool.
They especially started the development of the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;microsoft&#x2F;language-server-protocol&quot;&gt;Language Server Protocol&lt;&#x2F;a&gt;, that I use now also in Neovim.&lt;br &#x2F;&gt;
But in the long term, I feel that a real FOSS editor with an open extension&#x2F;plugin ecosystem, &lt;strong&gt;is the right choice&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;finding-an-alternative&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#finding-an-alternative&quot; aria-label=&quot;Anchor link for: finding-an-alternative&quot;&gt;Finding an alternative&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;It is not easy to find something similar to VSCode.&lt;br &#x2F;&gt;
This are my &lt;strong&gt;minimal requirements&lt;&#x2F;strong&gt;, in ascending order by importance&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;FOSS, for real&lt;&#x2F;li&gt;
&lt;li&gt;Fast opening and editing&lt;&#x2F;li&gt;
&lt;li&gt;Language Server Protocol support&lt;&#x2F;li&gt;
&lt;li&gt;Spell checker (since I make errors, a lot)&lt;&#x2F;li&gt;
&lt;li&gt;No telemetry&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Here some editors I tried to replace it&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;apps.kde.org&#x2F;kate&#x2F;&quot;&gt;KDE&#x27;s Kate&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;apps.kde.org&#x2F;kwrite&#x2F;&quot;&gt;KDE&#x27;s KWrite&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;help.gnome.org&#x2F;users&#x2F;gedit&#x2F;stable&#x2F;&quot;&gt;Gedit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.geany.org&#x2F;&quot;&gt;Geany&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;micro-editor.github.io&#x2F;&quot;&gt;Micro&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;zed.dev&#x2F;&quot;&gt;Zed&lt;&#x2F;a&gt; (after switching to Neovim)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;All without success.
They are all great editors, but I simply had the feeling, that it was time to &lt;strong&gt;really&lt;&#x2F;strong&gt; try Vim.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;it-all-started-with-a-big-bang-vim&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#it-all-started-with-a-big-bang-vim&quot; aria-label=&quot;Anchor link for: it-all-started-with-a-big-bang-vim&quot;&gt;It all started with &lt;del&gt;a big bang&lt;&#x2F;del&gt; Vim&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;So I chose &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.vim.org&#x2F;&quot;&gt;Vim&lt;&#x2F;a&gt; as my new text editor.
I could immediately feel the &lt;strong&gt;advantage&lt;&#x2F;strong&gt; of sticking to the keyboard as much as possible.
Everything is a &lt;strong&gt;few keystrokes away&lt;&#x2F;strong&gt; and is really fun.&lt;&#x2F;p&gt;
&lt;p&gt;After getting used to vim basics and motions, I wanted to give &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;neovim.io&#x2F;&quot;&gt;Neovim&lt;&#x2F;a&gt; a try.&lt;br &#x2F;&gt;
But lets check if my requirements fit Neovim.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;FOSS, for real&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Neovim is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&#x2F;blob&#x2F;master&#x2F;LICENSE.txt&quot;&gt;Apache 2.0&lt;&#x2F;a&gt;, and is based on Vim, with it&#x27;s own &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;vim&#x2F;vim&#x2F;blob&#x2F;master&#x2F;LICENSE&quot;&gt;Vim License&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;strong&gt;Fast opening and editing&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Opens instantly, even for big files&lt;br &#x2F;&gt;
&lt;strong&gt;Language Server Protocol support&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Full &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;neovim.io&#x2F;doc&#x2F;user&#x2F;lsp.html&quot;&gt;LSP support&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;strong&gt;Spell checker (since I make errors, a lot)&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
The simple command &lt;code&gt;:set spell&lt;&#x2F;code&gt; does the magic, already built-in!&lt;br &#x2F;&gt;
&lt;strong&gt;No telemetry&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
Or maybe &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&#x2F;pull&#x2F;17957&quot;&gt;there is&lt;&#x2F;a&gt;??&lt;&#x2F;p&gt;
&lt;h2 id=&quot;getting-the-latest-version-on-debian&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#getting-the-latest-version-on-debian&quot; aria-label=&quot;Anchor link for: getting-the-latest-version-on-debian&quot;&gt;Getting the latest version on Debian&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;My current OS of choice is Debian 12 bookworm.
Debian bookworm, at the time of writing, has Neovim version 0.7.2.
You can check the current version in Debian stable &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;packages.debian.org&#x2F;bookworm&#x2F;neovim&quot;&gt;here&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
This version is not compatible with latest package managers and plugins.
Most of them work with 0.9.5 upwards.&lt;br &#x2F;&gt;
So I needed to get the latest Neovim from elsewhere...&lt;&#x2F;p&gt;
&lt;h3 id=&quot;appimage&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#appimage&quot; aria-label=&quot;Anchor link for: appimage&quot;&gt;AppImage&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;First I tried Neovim&#x27;s official AppImage, you can find on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&#x2F;releases&quot;&gt;Github&lt;&#x2F;a&gt;.
It was a good first start and an easy way to try the latest version on Debian.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;building-from-source&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#building-from-source&quot; aria-label=&quot;Anchor link for: building-from-source&quot;&gt;Building from source&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;But after seeing ThePrimeagen building Neovim from source on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;ZWWxwwUsPNw?feature=shared&amp;amp;t=191&quot;&gt;YouTube&lt;&#x2F;a&gt;,
I also wanted to do that, to have a proper .deb package and drop the AppImage.&lt;&#x2F;p&gt;
&lt;p&gt;It was actually &lt;strong&gt;my first time&lt;&#x2F;strong&gt;, that I built a program from source and installed in on my machine.
That makes it a lot easier to contribute back to a project!
But well, for now I&#x27;m happy with my home built Neovim deb file.&lt;&#x2F;p&gt;
&lt;p&gt;Here a quick guide on how to build it by yourself.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Requirements&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; first, install build deps&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;apt&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; install&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;y&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; ninja-build&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; gettext&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; cmake&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; unzip&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; curl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; build-essential&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; clone neovim&amp;#39;s repo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; clone&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; https:&#x2F;&#x2F;github.com&#x2F;neovim&#x2F;neovim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; neovim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Build and install&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; check out stable tag, or specific version you prefer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; checkout&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; stable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; build neovim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;make&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; CMAKE_BUILD_TYPE=RelWithDebInfo&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;cd&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; build&lt;&#x2F;span&gt;&lt;span&gt; &amp;amp;&amp;amp;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; cpack&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;G&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; DEB&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; install it, as root&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;dpkg&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; nvim-linux64.deb&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Update&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; switch back to master&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; checkout&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; master&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pull&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; fetch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;-all&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; check out stable tag, or specific version you prefer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;git&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; checkout&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; stable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After getting the updates, you can &lt;strong&gt;build and install&lt;&#x2F;strong&gt; again.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;package-manager-s&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#package-manager-s&quot; aria-label=&quot;Anchor link for: package-manager-s&quot;&gt;Package manager(s)&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There are so many package managers and Neovim distributions, that it can be &lt;strong&gt;overwhelming&lt;&#x2F;strong&gt;.
I think everybody needs to explore this jungle &lt;strong&gt;on it&#x27;s own&lt;&#x2F;strong&gt;, get hands dirty and find what fits the most.&lt;&#x2F;p&gt;
&lt;p&gt;Many recommend starting from &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;nvim-lua&#x2F;kickstart.nvim&quot;&gt;kickstart&lt;&#x2F;a&gt;, and maybe I also should have done that too.
After days of restarting from scratch, trying this and trying that, I sticked with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;junegunn&#x2F;vim-plug&quot;&gt;vim-plug&lt;&#x2F;a&gt; for now.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;plugins&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#plugins&quot; aria-label=&quot;Anchor link for: plugins&quot;&gt;Plugins&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;After thinking that Neovim has tons of package managers, I haven&#x27;t yet seen the huge number of plugins.
Multiple plugins that solve the same issue, just maybe written in Lua or with fancy icons.
Many times there is no right or wrong, old or new.
My recommendation is &lt;strong&gt;listen to your gut, and don&#x27;t overthink it&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I saw many videos and articles on the web, where users had at least 50 plugins installed.
There are even benchmarks the opening of Neovim in &lt;strong&gt;milliseconds&lt;&#x2F;strong&gt; where 40ms is the usual &quot;fast enough&quot; value.
Since I&#x27;m still in my early Neovim days, I have around 20 plugins installed.
But surely more are coming, and my first benchmark waits behind the corner.&lt;&#x2F;p&gt;
&lt;p&gt;But there is also the thing, that plugins &lt;strong&gt;might break&lt;&#x2F;strong&gt; during updates etc...
I haven&#x27;t encountered that yet, but I guess, &lt;strong&gt;less plugins is better&lt;&#x2F;strong&gt; in that sense.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;configure-with-init-lua&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#configure-with-init-lua&quot; aria-label=&quot;Anchor link for: configure-with-init-lua&quot;&gt;Configure with init.lua&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can adapt Neovim as you prefer with all the plugins available.
Or even write some own scripts in Lua.&lt;&#x2F;p&gt;
&lt;p&gt;But first you need a init.lua file.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;mdir&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; .config&#x2F;nvim&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;touch&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; .config&#x2F;nvim&#x2F;init.lua&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now you can watch hours of videos and read articles and books about vim.
The grind will never stop, unless you finally admit that you are wasting to much time in configuring your editor.
At some point you simply have to accept that &lt;strong&gt;it&#x27;s good enough&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can find my current Neovim configuration file on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;dotfiles&quot;&gt;Codeberg&lt;&#x2F;a&gt; or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;dotfiles&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;look-ma-no-mouse&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#look-ma-no-mouse&quot; aria-label=&quot;Anchor link for: look-ma-no-mouse&quot;&gt;Look Ma, no mouse&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now that I&#x27;m keyboard addicted, I also started using shortcuts whenever I can.&lt;&#x2F;p&gt;
&lt;p&gt;I use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;swaywm.org&#x2F;&quot;&gt;sway&lt;&#x2F;a&gt;, as my &lt;strong&gt;tiling window manager&lt;&#x2F;strong&gt; on Debian.
With a few keystrokes you can switch workspaces, open terminals and align windows at the speed of typing.
And everything is a &lt;strong&gt;configuration file&lt;&#x2F;strong&gt;, like in Neovim.
So the next time you re-install your OS, you just need to get the file and get back where you left off.
If something breaks or you don&#x27;t like some changes, simply &lt;code&gt;git revert&lt;&#x2F;code&gt; everything.&lt;&#x2F;p&gt;
&lt;p&gt;I also started to use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;support.mozilla.org&#x2F;en-US&#x2F;kb&#x2F;keyboard-shortcuts-perform-firefox-tasks-quickly&quot;&gt;Firefox shortcuts&lt;&#x2F;a&gt;,
like open a new tab with &lt;strong&gt;ctrl+t&lt;&#x2F;strong&gt;, close it with &lt;strong&gt;ctrl+w&lt;&#x2F;strong&gt; or cycle trough tabs with &lt;strong&gt;ctrl+pgup&lt;&#x2F;strong&gt; and &lt;strong&gt;ctrl+pgdn&lt;&#x2F;strong&gt;.
Then there is &lt;strong&gt;F6&lt;&#x2F;strong&gt; to focus the address bar or &lt;strong&gt;ctrl+shift+p&lt;&#x2F;strong&gt; for private browsing.&lt;br &#x2F;&gt;
I even tried &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;addons.mozilla.org&#x2F;en-US&#x2F;firefox&#x2F;addon&#x2F;vimium-ff&#x2F;&quot;&gt;Vimium&lt;&#x2F;a&gt;, a Vim Firefox extension to get vim navigation.
But there I drew the line and went back to endless scrolling, with the mouse...&lt;&#x2F;p&gt;
&lt;p&gt;As you can see, Neovim is not just an editor, it is a &lt;strong&gt;life style&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>I quit my job to go full indie</title>
          <pubDate>Mon, 16 Sep 2024 09:25:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/full-time-gamedev/</link>
          <guid>https://simondalvai.org/blog/full-time-gamedev/</guid>
          <description xml:base="https://simondalvai.org/blog/full-time-gamedev/">&lt;p&gt;I&#x27;m excited to announce that today is my first official day as a full time &lt;strong&gt;indie game developer&lt;&#x2F;strong&gt;.
After three years of CI&#x2F;CD pipelines, several software migrations and bug fixes at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;noi.bz.it&#x2F;en&#x2F;&quot;&gt;NOI Techpark&lt;&#x2F;a&gt;, it was time to say goodbye.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-plan&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-plan&quot; aria-label=&quot;Anchor link for: the-plan&quot;&gt;The plan&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;It was never my plan to become full time indie dev, because I thought that making games is just a hobby and a nice way to pass my free time.
But things have changed and my games became too complex to be developed properly in my limited free time.
So I had the feeling, that I need to try this adventure and see where it leads.&lt;&#x2F;p&gt;
&lt;p&gt;Now I can dedicate my whole day to my games, this blog and all the CI&#x2F;CD pipelines I created for Godot and libGDX.
My main focus will be the game that got too big to handle in my free time, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;futsal-manager&#x2F;&quot;&gt;Futsal Manager&lt;&#x2F;a&gt;.
I plan to release the first early access on Steam and itch.io early 2025.
Having around half a year time, to finish my game, I feel that this date might actually be true this time.
(I&#x27;ve been promising to finish this game to my friends already too many times)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-experiment&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-experiment&quot; aria-label=&quot;Anchor link for: the-experiment&quot;&gt;The experiment&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This whole &quot;project&quot; is actually an experiment, to see if I can make a living with &lt;strong&gt;Free and Open Source games&lt;&#x2F;strong&gt;.
I truly believe, that the game development world can profit from Open Source games.
There are already really nice Open Source game engines and libraries, like the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;godotengine.org&#x2F;&quot;&gt;Godot Engine&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;libgdx.com&#x2F;&quot;&gt;libGDX&lt;&#x2F;a&gt;.
I never used a closed source engine like Unity or similar, so I can&#x27;t really compare them.
But the bad news Unity had in the past months, show that betting on a Open Source and community built engine, is the road to go.&lt;&#x2F;p&gt;
&lt;p&gt;I also believe that gamers will profit the most from Open Source games.
Being Open Source, limits the way one can profit from it, but in my opinion in a good way.
Business models like packing the game with ads or micro transactions don&#x27;t really fit in the Open Source world.
Someone could simply make a copy of your game without ads, micro-transactions or a season pass.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;making-a-living-with-foss-games&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#making-a-living-with-foss-games&quot; aria-label=&quot;Anchor link for: making-a-living-with-foss-games&quot;&gt;Making a living with FOSS games&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There surely are and will be many other business models, that are FOSS compatible.
For now, I will simply follow the way &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mindustrygame.github.io&#x2F;&quot;&gt;Mindustry&lt;&#x2F;a&gt; does it.
You can get free copies of the game on itch.io, flathub, F-Droid etc... and a payed version on Steam.&lt;br &#x2F;&gt;
This seems the easiest and safest way to do get some dollars out of a Open Source game.
It solves the cheaper clone of the game problem, because I will offer the cheapest (free) alternative on the market.&lt;&#x2F;p&gt;
&lt;p&gt;Surely this &quot;business plan&quot; is not compatible with big AAA game studios, but who knows, maybe some day we will see a AAA Open Source game.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-comes-next&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-comes-next&quot; aria-label=&quot;Anchor link for: what-comes-next&quot;&gt;What comes next&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Now you will hear much more from me, here in my blog and on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mastodon.social&#x2F;@dulvui&quot;&gt;Mastodon&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
My git-steak (at the time of writing: over 1 year a commit a day) will continue and grow much bigger.
I&#x27;m also considering some live development streams on Twitch and videos on YouTube.
But for now, I will concentrate on finishing Futsal Manager.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Use websockets in Godot on itch.io with Caddy</title>
          <pubDate>Mon, 26 Aug 2024 16:10:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-websocket-itchio/</link>
          <guid>https://simondalvai.org/blog/godot-websocket-itchio/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-websocket-itchio/">&lt;p&gt;To use websockets within your Godot game on itch.io, or any other website, a &lt;strong&gt;secure&lt;&#x2F;strong&gt; websocket connection, aka &lt;code&gt;wss:&#x2F;&#x2F;&lt;&#x2F;code&gt;, is mandatory.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;WARNING&lt;&#x2F;strong&gt;: This is probably not the correct way to secure Godot&#x27;s websocket connections.
I&#x27;m using this setup only for some &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;condor&#x2F;&quot;&gt;real-time auction tool&lt;&#x2F;a&gt; I created for personal use only.
Please inform yourself, before using this in production.&lt;br &#x2F;&gt;
If you know the correct way how to solve this (or this actually is the correct way), please le me know!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;caddy-for-the-rescue&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#caddy-for-the-rescue&quot; aria-label=&quot;Anchor link for: caddy-for-the-rescue&quot;&gt;Caddy for the rescue&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&#x2F;&quot;&gt;caddy webserver&lt;&#x2F;a&gt;, by default, automatically obtains and renews TLS certificates for all your sites and applications.
This includes your websocket server!&lt;&#x2F;p&gt;
&lt;p&gt;With this simple Caddyfile, your websocket server is ready.
Change the &lt;code&gt;8000&lt;&#x2F;code&gt; port to whatever port you are using.
Also the &lt;code&gt;&#x2F;ws&#x2F;*&lt;&#x2F;code&gt; can be changed to &lt;code&gt;&#x2F;whatever&#x2F;*&lt;&#x2F;code&gt; you prefer.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;your.dom.ain&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        reverse_proxy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &#x2F;ws&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; localhost:8000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        handle&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &#x2F;ws&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;*&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;                reverse_proxy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; localhost:8000&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In your Godot client code, you can simply put the secure websocket url.&lt;br &#x2F;&gt;
Just make sure you use &lt;code&gt;wss:&#x2F;&#x2F;&lt;&#x2F;code&gt; instead of &lt;code&gt;ws:&#x2F;&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const HOST: String = &amp;quot;wss:&#x2F;&#x2F;your.dom.ain&#x2F;ws&#x2F;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now you can play your game on itch.io or other websites!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;client-server-code&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#client-server-code&quot; aria-label=&quot;Anchor link for: client-server-code&quot;&gt;Client&#x2F;Server code&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;godotengine&#x2F;godot-demo-projects&quot;&gt;godot-demo-projects&lt;&#x2F;a&gt; repository has great code examples for networking.&lt;&#x2F;p&gt;
&lt;p&gt;My application uses the code from there and can be found here&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;condor&#x2F;blob&#x2F;main&#x2F;app&#x2F;src&#x2F;websocket&#x2F;client&#x2F;client.gd&quot;&gt;client&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;condor&#x2F;tree&#x2F;main&#x2F;server&#x2F;src&quot;&gt;server&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;This is an application for managing an auction for the Italian fantasy football game &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.fantacalcio.it&#x2F;&quot;&gt;Fantacalcio&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
In this code, the server is just forwarding the messages from one client to all other connected clients.
The server does not store any data or state.
If needed, you can extend the server with more logic, handling sessions, store data etc...&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Personal blog, as a solo game dev?</title>
          <pubDate>Wed, 24 Jul 2024 21:30:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/solo-gamedev-blog/</link>
          <guid>https://simondalvai.org/blog/solo-gamedev-blog/</guid>
          <description xml:base="https://simondalvai.org/blog/solo-gamedev-blog/">&lt;p&gt;Yes, it is worth it, &lt;strong&gt;if you like writing&lt;&#x2F;strong&gt; (or nowadays, prefer to let some fancy VC backed LLM service do the writing).
No worries, my blog posts are still written by crystallizing words out of my by brain.
All (grammar and syntax errors) inclusive.&lt;br &#x2F;&gt;
If you don&#x27;t like writing at all, I still recommend having a simple personal webpage with at least the list of your created games.
It is also great to host privacy policies for your games, that is mandatory for Google Play Store and Apple App Store.&lt;&#x2F;p&gt;
&lt;p&gt;I started with game development as a hobby around 2018 and created some games.
Since the end of 2022, I also have this personal website with a blog, where I post monthly something about game dev or other things I find interesting.&lt;&#x2F;p&gt;
&lt;p&gt;Here I share my experience on having a personal blog as a solo game developer.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hosting-github-pages-vs-self-hosting&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#hosting-github-pages-vs-self-hosting&quot; aria-label=&quot;Anchor link for: hosting-github-pages-vs-self-hosting&quot;&gt;Hosting: Github Pages vs Self hosting&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The first year I hosted my website on Github Pages.
It is completely free and gives you a great starting point for your personal webpage.
It works pretty well and within minutes, you can have a website with the url [your username].github.io online.
If you want to use a custom domain, this is also quite easy, but may vary between domain service provider.
So I won&#x27;t go into detail on this topic.&lt;&#x2F;p&gt;
&lt;p&gt;Since January 2024, I&#x27;m hosting my website on a shared cloud server on Hetzner running  &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;caddyserver.com&quot;&gt;Caddy&lt;&#x2F;a&gt; on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;debian.org&quot;&gt;Debian&lt;&#x2F;a&gt;.
That costs me around 5€&#x2F;month for now, but gives me &lt;strong&gt;more control and insights&lt;&#x2F;strong&gt; over my website.
By self hosting, I can see the access logs on the server, to get a rough overview on how many users and bots (there are a lot crawlers out there) are visiting.
Then I can also use some features like caching or URL redirects, that Github Pages doesn&#x27;t provide.&lt;&#x2F;p&gt;
&lt;p&gt;I also don&#x27;t really know how and if Github (and Microsoft) are using the traffic on Github Pages to &lt;strong&gt;track users&lt;&#x2F;strong&gt; and process&#x2F;sell the data.
I would guess, yes they to, since nothing comes for free if it is provided by a big tech company.
So if you care about privacy, self hosting might be the better choice.&lt;&#x2F;p&gt;
&lt;p&gt;My recommendation is to use Github Pages or similar to get started, if you have no experience with self hosting.
Then slowly start playing around with some servers, when you start getting bored with your setup :-)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;visibility&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#visibility&quot; aria-label=&quot;Anchor link for: visibility&quot;&gt;Visibility&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This blog has increased the visibility of my website and games a lot.
I guess &lt;strong&gt;90% traffic&lt;&#x2F;strong&gt; of my website, comes from my blog post.
I can&#x27;t give exact numbers, because I not using any user tracking and analytic tools on my websites and games.
But there are some tools that still can give you a rough number, on how many users you reach.
It is also really helpful to see which blog posts or games attract the most users, organically.
Every user that reads your blog post is a potential player of your games.
From reading a blog post, to downloading a game might be only 2 more clicks.&lt;&#x2F;p&gt;
&lt;p&gt;You can then further increase the visibility of your content by posting on other websites.
I normally post them on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;&quot;&gt;hackernews&lt;&#x2F;a&gt;, mastodon and sometimes on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;reddit.com&quot;&gt;reddit&lt;&#x2F;a&gt;.
It is incredible how much traffic you can get, once something got up voted a lot.&lt;&#x2F;p&gt;
&lt;p&gt;As an example: the most views I got on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.itch.io&#x2F;&quot;&gt;itch.io&lt;&#x2F;a&gt; was, when I landed on the front page of hackernews for some hours with this &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=36466698&quot;&gt;blog post&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;building-an-audience&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#building-an-audience&quot; aria-label=&quot;Anchor link for: building-an-audience&quot;&gt;Building an audience&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Some people will read and like your blog posts and games.
If you have an RSS feed or post on social networks, you might even have people that reads your content immediately, when it is released.
I currently have a really small audience, but I&#x27;m pretty sure this is how it works for successful people :-)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;market-share-discovery&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#market-share-discovery&quot; aria-label=&quot;Anchor link for: market-share-discovery&quot;&gt;Market share discovery&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;By having a website of your game and Google Search Console enabled, you can see if people search for your game already.
This can be really motivating, if your game&#x27;s website gets views, even before it is released.
This actually happens right now for my game &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;futsal-manager&#x2F;&quot;&gt;Futsal Manager&lt;&#x2F;a&gt;.
I get daily visits and occasionally e-mails because of it, and I haven&#x27;t released the game yet.&lt;&#x2F;p&gt;
&lt;p&gt;So this means that once I release the game, I already know that some people will search for in and find it.
All organically and for free.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tracking&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tracking&quot; aria-label=&quot;Anchor link for: tracking&quot;&gt;Tracking&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I don&#x27;t use any user tracking tool in my games or website.
This makes makes it hard to understand, what content users like, and what not.
But there are still some &lt;strong&gt;tools and tricks&lt;&#x2F;strong&gt; out there, to get a rough estimate.
I currently use the Google Search console and get some data from the caddy web-server logs.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;google-search-console&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#google-search-console&quot; aria-label=&quot;Anchor link for: google-search-console&quot;&gt;Google Search Console&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;You can get a good search engine performance overview using the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;search.google.com&#x2F;search-console&quot;&gt;Google Search Console&lt;&#x2F;a&gt;.
For that you just need a Google Account and verify ownership of the websites you want to &quot;track&quot;.
Google will give you some data on how many users have seen you page in their results, clicked on it and what the keywords where.&lt;&#x2F;p&gt;
&lt;p&gt;Even more interesting to me is the list of websites that &lt;strong&gt;link back&lt;&#x2F;strong&gt; to you website.
Here you might find that your blog post has been shared on some social network or cited in some article.&lt;&#x2F;p&gt;
&lt;p&gt;Here of course you&#x27;ll see only data from people using the Google Search.
But they still have a huge market share in the web search world.
I would guess by adding 10% to the number you see in the Google Search Console, should make the real value.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;caddy-logs&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#caddy-logs&quot; aria-label=&quot;Anchor link for: caddy-logs&quot;&gt;Caddy logs&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;goaccess.io&#x2F;&quot;&gt;go-access&lt;&#x2F;a&gt; to analyze the caddy logs.
It works well in the terminal or browser, is really fast and supports a vast variety of log formats.
I tried to setup a nice looking Grafana dashboard, but as it didn&#x27;t worked as expected, I felt that the effort is not worth it.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;don-t-forget-about-your-games&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#don-t-forget-about-your-games&quot; aria-label=&quot;Anchor link for: don-t-forget-about-your-games&quot;&gt;Don&#x27;t forget about your games&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;So having a personal blog will help you a lot to promote your games and to get visibility.
But I have spent a lot of time creating this website and writing all the blog posts.
Maybe too much, maybe not, who knows.
Sure is, every minute I spend here, I don&#x27;t work on my games.&lt;&#x2F;p&gt;
&lt;p&gt;So my most important advice is: don&#x27;t get too much distracted by other shiny things and &lt;strong&gt;build great games!&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>99Managers™ Futsal Edition FAQ</title>
          <pubDate>Sun, 23 Jun 2024 19:20:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/99managers-futsal-faq/</link>
          <guid>https://simondalvai.org/blog/99managers-futsal-faq/</guid>
          <description xml:base="https://simondalvai.org/blog/99managers-futsal-faq/">&lt;p&gt;There is now a &lt;strong&gt;new and updated&lt;&#x2F;strong&gt; &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;99managers.org&#x2F;faq&#x2F;&quot;&gt;FAQ&lt;&#x2F;a&gt; on 99managers.org, the official website of the game.&lt;br &#x2F;&gt;
I will keep this blog post online, because why not?
It can be funny to read this in some years, when the game took off or crashed miserably :-)
Only time will tell...&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;app&#x2F;3334770&#x2F;99Managers_Futsal_Edition&#x2F;&quot;&gt;Wishlist now on Steam!&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;br &#x2F;&gt;
&lt;strong&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.itch.io&#x2F;99managers-futsal-edition&quot;&gt;Play the beta on itch.io&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-teams-players-will-be-in-the-game&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-teams-players-will-be-in-the-game&quot; aria-label=&quot;Anchor link for: what-teams-players-will-be-in-the-game&quot;&gt;What teams&#x2F;players will be in the game?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;There will be &lt;strong&gt;no real teams and players&lt;&#x2F;strong&gt; in the game.
Fantasy teams and players will be generated by a script and will have random names and attributes.&lt;&#x2F;p&gt;
&lt;p&gt;The script works with a seed, to have always the same teams and players, if the same seed is used.
You might remember this from Minecraft, where the same seed mechanism is used for random world generation.&lt;&#x2F;p&gt;
&lt;p&gt;Having real teams and player names is a lot of work, legal headache and simply too much work for me alone.
An in-game editor could be a future solution to this problem.
With an in-game editor, you will be able to create your own players and possibly share the lists with others.
Another even simpler solution could be to simply add a csv import&#x2F;export functionality.
This is on my to-do list, for the future.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;when-will-the-game-be-available&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#when-will-the-game-be-available&quot; aria-label=&quot;Anchor link for: when-will-the-game-be-available&quot;&gt;When will the game be available?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The game will be released 2025 and the exact date has still to be defined.
There is a &lt;strong&gt;beta version&lt;&#x2F;strong&gt; available on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.itch.io&#x2F;99managers-futsal-edition&quot;&gt;itch.io&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;I started working on the game on 11th July 2020 and a lot happened since then.
I migrated it from Godot 3.5 to 4, rewrote the Match engine several times and there is still much to do.
I worked only in my free time on this game, while having a full time job.
Since September 2024 I&#x27;m working full time on this game.&lt;&#x2F;p&gt;
&lt;p&gt;I do my very best to finish the game as soon as possible.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-can-the-game-be-played&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#where-can-the-game-be-played&quot; aria-label=&quot;Anchor link for: where-can-the-game-be-played&quot;&gt;Where can the game be played?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This will be my first Desktop game released on Steam.
So it will be available for &lt;strong&gt;Linux&lt;&#x2F;strong&gt;, &lt;strong&gt;Windows&lt;&#x2F;strong&gt; and &lt;strong&gt;MacOS&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;For now no (official) mobile release is planned, since it is quite difficult to fit the content on small screens with touch support.
But once the game is released on Desktop, a mobile release might follow.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-much-will-the-game-cost&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-much-will-the-game-cost&quot; aria-label=&quot;Anchor link for: how-much-will-the-game-cost&quot;&gt;How much will the game cost?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This might be my first game with a price, but I&#x27;m not sure how much.
I guess it will be between 5€ and 10€ on Steam, depending how the game will look and feel at first release.&lt;&#x2F;p&gt;
&lt;p&gt;The same game without modification will always be available for free on itch.io.
Once the beta period is over, the game will also be available for free on other platforms like flathub.org.&lt;&#x2F;p&gt;
&lt;p&gt;This game is Free and Open Source, under the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;AGPL-3.0-or-later&quot;&gt;AGPL v3.0 or later&lt;&#x2F;a&gt; license.
That means that you are free to &lt;strong&gt;study, modify, improve and share&lt;&#x2F;strong&gt; the source code.
So technically you will always be able to build your own version of the game at no cost.
You just need the source code, the Godot Engine editor and some guide on how to build an executable, if you don&#x27;t know already how to do that.
There will be a guide available in the repositories README, as soon the game is stable enough.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;this-sounds-great-can-i-help-somehow&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#this-sounds-great-can-i-help-somehow&quot; aria-label=&quot;Anchor link for: this-sounds-great-can-i-help-somehow&quot;&gt;This sounds great, can I help somehow?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Until the game is still in an unstable development phase, like now, I prefer to work alone on the game.
But as soon the game is in a stable state, you can contribute your ideas and especially &lt;strong&gt;bug fixes&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you can&#x27;t code, you still can help by &lt;strong&gt;translating the game&lt;&#x2F;strong&gt; to other languages.
There is a dedicated page on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;hosted.weblate.org&#x2F;projects&#x2F;99-managers-futsal-edition&#x2F;&quot;&gt;weblate.org&lt;&#x2F;a&gt;,
where everybody can add new languages and improve existing translations.&lt;&#x2F;p&gt;
&lt;p&gt;And of course, you can also help me a lot by &lt;strong&gt;spreading the word&lt;&#x2F;strong&gt; about the game.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Godot static types, a hidden gem</title>
          <pubDate>Wed, 29 May 2024 21:20:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-static-typing/</link>
          <guid>https://simondalvai.org/blog/godot-static-typing/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-static-typing/">&lt;p&gt;GDScript is a dynamic typed language, but you can add type hints, that make it a Static Typed language.
This increases &lt;strong&gt;performance&lt;&#x2F;strong&gt; and helps to &lt;strong&gt;avoid bugs.&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;So let&#x27;s see how to use Static Types and get the most out of them.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;hello-godot-s-typing-system&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#hello-godot-s-typing-system&quot; aria-label=&quot;Anchor link for: hello-godot-s-typing-system&quot;&gt;Hello Godot&#x27;s typing system&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Variables can be defined in the following ways&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# dynamic&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var a = &amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# automatic type guess&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var b := &amp;quot;hello&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# static typing&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var c: String = &amp;quot;hello&amp;quot; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;It is highly recommended to use one typing system across your project.&lt;br &#x2F;&gt;
I suggest to &lt;strong&gt;always use static typing&lt;&#x2F;strong&gt;, even for small projects.
This can help to &lt;strong&gt;prevent errors&lt;&#x2F;strong&gt; before even the game runs.&lt;br &#x2F;&gt;
With dynamic typing, you could have a bug in your code, and only see it while playing.
Your game might run fine, until the specific code with the error gets executed.&lt;&#x2F;p&gt;
&lt;p&gt;It is also a wise choice, to use Static Typing from the very &lt;strong&gt;beginning of the project&lt;&#x2F;strong&gt;.
Making a project Static Typed afterwards, can be quite time consuming and frustrating.&lt;br &#x2F;&gt;
Trust me, I&#x27;ve been there already...&lt;&#x2F;p&gt;
&lt;h2 id=&quot;project-settings-to-have-stricter-error-checks&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#project-settings-to-have-stricter-error-checks&quot; aria-label=&quot;Anchor link for: project-settings-to-have-stricter-error-checks&quot;&gt;Project settings to have stricter error checks&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;First you have to enable Advanced settings in the Project Settings.
Then under &lt;strong&gt;Debug&lt;&#x2F;strong&gt; -&amp;gt; &lt;strong&gt;GDScript&lt;&#x2F;strong&gt; you can change how the editor handles different warnings as errors and vice versa.
Changing here some warnings to errors can be game changing and really important to bring real static typing advantages.&lt;&#x2F;p&gt;
&lt;p&gt;Here the setup I&#x27;m currently using:
&lt;img class=&quot;image image-wide&quot; src=&quot;gdscript-debug-settings.webp&quot; alt=&quot;Changed warnings to errors in Project settings&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;In Editor Settings, you can also enable &lt;strong&gt;Add Type Hints&lt;&#x2F;strong&gt; under Text Editor -&amp;gt; Completition -&amp;gt; Add Type Hints, to get automated type hints by the editor.
So for example, when you let Godot auto complete a function, the editor adds the type hints.&lt;&#x2F;p&gt;
&lt;p&gt;Another good habit is to use &lt;strong&gt;class_name&lt;&#x2F;strong&gt; in your custom Nodes as much as possible.
With static typing and class_name you can get auto complete for functions and variables.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Tip:&lt;&#x2F;strong&gt; to add a Node from the Node tree directly into the script, simply click the node with the mouse, press Ctrl and drag it into the script.
This works also with multiple selected Nodes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;code-examples&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#code-examples&quot; aria-label=&quot;Anchor link for: code-examples&quot;&gt;Code examples&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;First, lets create a simple static class script.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name StaticClass&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Node&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var alice: String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;wrong-type-dynamic-static-type&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#wrong-type-dynamic-static-type&quot; aria-label=&quot;Anchor link for: wrong-type-dynamic-static-type&quot;&gt;Wrong type &amp;amp; Dynamic Static Type&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;In another file, let&#x27;s try to assign a &lt;strong&gt;wrong type&lt;&#x2F;strong&gt; to &lt;code&gt;alice&lt;&#x2F;code&gt;, that is a actually a String&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Node2D&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _ready() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    var static_class = StaticClass.new()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    static_class.alice = 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We will get the following error message, &lt;strong&gt;after&lt;&#x2F;strong&gt; starting the Scene.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Error: Invalid set index &amp;#39;alice&amp;#39; (on base: &amp;#39;Node (StaticClass)&amp;#39;) with value of type &amp;#39;int&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;wrong-type-static-type&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#wrong-type-static-type&quot; aria-label=&quot;Anchor link for: wrong-type-static-type&quot;&gt;Wrong type &amp;amp; Static Type&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Let&#x27;s try to assign a &lt;strong&gt;wrong type&lt;&#x2F;strong&gt; to &lt;code&gt;alice&lt;&#x2F;code&gt;, but with Static Typing for &lt;code&gt;static_class&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Node2D&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _ready() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    var static_class:StaticClass = StaticClass.new()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    static_class.alice = 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We will see the following error message, &lt;strong&gt;before&lt;&#x2F;strong&gt; starting the Scene.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Cannot assign a value of type &amp;quot;int&amp;quot; as &amp;quot;String&amp;quot;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h3 id=&quot;nonexistent-variable-dynamic-type&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nonexistent-variable-dynamic-type&quot; aria-label=&quot;Anchor link for: nonexistent-variable-dynamic-type&quot;&gt;Nonexistent variable &amp;amp; Dynamic Type&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Now, let&#x27;s try to access a &lt;strong&gt;nonexistent variable&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Node2D&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _ready() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    var static_class = StaticClass.new()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    static_class.bob = 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We will get the following error message, &lt;strong&gt;after&lt;&#x2F;strong&gt; starting the Scene as a error message in the editor.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Error: Invalid set index &amp;#39;bob&amp;#39; (on base: &amp;#39;Node (StaticClass)&amp;#39;) with value of type &amp;#39;int&amp;#39;.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So same error as before, but actually a different problem.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;nonexistent-variable-static-type-inferred-declaration&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#nonexistent-variable-static-type-inferred-declaration&quot; aria-label=&quot;Anchor link for: nonexistent-variable-static-type-inferred-declaration&quot;&gt;Nonexistent variable &amp;amp; Static Type &amp;amp; Inferred Declaration&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;If &lt;strong&gt;Inferred Declaration&lt;&#x2F;strong&gt; is enabled as error in project settings, you get an error directly in the editor, &lt;strong&gt;before&lt;&#x2F;strong&gt; starting the Scene.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Node2D&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _ready() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    var static_class: StaticClass = StaticClass.new()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    static_class.bob = 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Note: You might need to restart the editor, to see the effects.&lt;&#x2F;p&gt;
&lt;p&gt;Here the error message.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;The property &amp;quot;bob&amp;quot; is not present on the inferred type &amp;quot;StaticClass&amp;quot; (but may be present on a subtype). (Warning treated as error.)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So using Static Typing and having some Debug Settings changed to error, we can see errors, before running the game.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#further-reading&quot; aria-label=&quot;Anchor link for: further-reading&quot;&gt;Further reading&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The best place to read in general about Godot are the official docs, since they will be up to date and explain everything.&lt;br &#x2F;&gt;
Here the official docs about &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;scripting&#x2F;gdscript&#x2F;static_typing.html&quot;&gt;Static Typing&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;I tried some performance benchmarks with static typed and dynamic typed code, but haven&#x27;t found any significant difference.
Probably I simply did the wrong operations, where this performance gain is not really visible.&lt;br &#x2F;&gt;
If you have some example, please let me know, so I can extend this article.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Happy JS Naked Day 2024</title>
          <pubDate>Tue, 23 Apr 2024 20:20:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/js-naked-day-2024/</link>
          <guid>https://simondalvai.org/blog/js-naked-day-2024/</guid>
          <description xml:base="https://simondalvai.org/blog/js-naked-day-2024/">&lt;p&gt;After I missed this year&#x27;s &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;css-naked-day.github.io&#x2F;&quot;&gt;CSS Naked Day&lt;&#x2F;a&gt; on 9th of April, I&#x27;m happy to participate to the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;js-naked-day.org&#x2F;&quot;&gt;JS Naked Day&lt;&#x2F;a&gt; on 24th of April.&lt;&#x2F;p&gt;
&lt;p&gt;My website is not yet ready to work without CSS.
All images miss static size tags and everything is messed up and is not usable without CSS right now.
So hopefully next year, my website will be ready for CSS Naked Day.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-no-js-is-important&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-no-js-is-important&quot; aria-label=&quot;Anchor link for: why-no-js-is-important&quot;&gt;Why no JS is important?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;&lt;em&gt;The web should work without JavaScript.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;This is the first statement on the JS Naked Day&#x27;s &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;js-naked-day.org&#x2F;&quot;&gt;website&lt;&#x2F;a&gt;.
I totally agree with this.
So many sites are overblown with JS scripts that could work also without it.&lt;&#x2F;p&gt;
&lt;p&gt;I can understand that in some cases JS is useful and makes sense, but I feel that more times the opposite is true.
My favorite &quot;overblown JS moments&quot; are, when I open a website and my laptop fan starts blowing out of nowhere.
That always reminds me how important the right usage of JS is.&lt;&#x2F;p&gt;
&lt;p&gt;You can find more interesting reasons to avoid JS on the JS Naked Day&#x27;s &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;js-naked-day.org&#x2F;&quot;&gt;website&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;this-will-never-have-js&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#this-will-never-have-js&quot; aria-label=&quot;Anchor link for: this-will-never-have-js&quot;&gt;This will never have JS&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;My main philosophy for this website is to have no JS at all, never, period.
So I had no JS to be removed or similar for JS Naked Day, just write this blog post :-)&lt;&#x2F;p&gt;
&lt;p&gt;I use &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.getzola.org&#x2F;&quot;&gt;zola&lt;&#x2F;a&gt;, a static site generator, similar to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gohugo.io&#x2F;&quot;&gt;hugo&lt;&#x2F;a&gt;, but in my opinion still less bloated and kept simple.
JS could be used, but I try to do everything without it, like here: &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;css-only-darkmode&#x2F;&quot;&gt;CSS only dark mode without JS&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Of course my website is really simple and has no sophisticated user interaction or similar, but shouldn&#x27;t be most websites like this?&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>How to publish Godot games on Flathub, in a nutshell</title>
          <pubDate>Tue, 26 Mar 2024 21:25:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-flathub-publish/</link>
          <guid>https://simondalvai.org/blog/godot-flathub-publish/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-flathub-publish/">&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;flathub.org&#x2F;&quot;&gt;Flathub&lt;&#x2F;a&gt; is an Open Source and community driven App Store for any GNU&#x2F;Linux system.
Recently I published my two Godot games &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;flathub.org&#x2F;apps&#x2F;org.simondalvai.ball2box&quot;&gt;Ball2Box&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;flathub.org&#x2F;apps&#x2F;org.simondalvai.pocket-broomball&quot;&gt;Pocket Broomball&lt;&#x2F;a&gt; on Flathub.&lt;br &#x2F;&gt;
Both use Godot Engine 3.5 base image, so this post will focus on version 3.5, but you can check for other Godot versions &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;flathub&#x2F;org.godotengine.godot.BaseApp&quot;&gt;in the BaseApp&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;flathub-submission&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#flathub-submission&quot; aria-label=&quot;Anchor link for: flathub-submission&quot;&gt;Flathub submission&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You should always read the official submission docs of Flathub, to know the latest and correct &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.flathub.org&#x2F;docs&#x2F;for-app-authors&#x2F;submission&#x2F;&quot;&gt;steps&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;In a nutshell, the process is the following&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Fork Flathub repo&lt;&#x2F;li&gt;
&lt;li&gt;Create files
&lt;ol&gt;
&lt;li&gt;manifest&lt;&#x2F;li&gt;
&lt;li&gt;appdata.xml&lt;&#x2F;li&gt;
&lt;li&gt;desktop file&lt;&#x2F;li&gt;
&lt;li&gt;256x256 icon&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Open pull request&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;manifest-file&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#manifest-file&quot; aria-label=&quot;Anchor link for: manifest-file&quot;&gt;Manifest file&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The main file of a Flatpak app is the manifest file, containing all &lt;strong&gt;information needed to build the app&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;pp-id&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;rg.simondalvai.ball2box&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;untime&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;rg.freedesktop.Platform&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;untime-version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;23.08&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;dk&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;rg.freedesktop.Sdk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ase&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;rg.godotengine.godot.BaseApp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Godot version&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ase-version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;3.5-23.08&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ommand&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;odot-runner&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;inish-args&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;share=ipc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;socket=x11&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; &amp;lt;-- Godot needs X11&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;socket=pulseaudio&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; --&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;device=dri&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;odules&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;all2Box&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;uildsystem&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;imple&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;uild-commands&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; The game itself&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;nstall Ball2Box.pck &#x2F;app&#x2F;bin&#x2F;godot-runner.pck&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Metadata and a .desktop file&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;nstall -D org.simondalvai.ball2box.desktop &#x2F;app&#x2F;share&#x2F;applications&#x2F;org.simondalvai.ball2box.desktop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;nstall -D org.simondalvai.ball2box.appdata.xml &#x2F;app&#x2F;share&#x2F;metainfo&#x2F;org.simondalvai.ball2box.metainfo.xml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; Icons&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;nstall -D icon-256.png &#x2F;app&#x2F;share&#x2F;icons&#x2F;hicolor&#x2F;256x256&#x2F;apps&#x2F;org.simondalvai.ball2box.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ources&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; The game is pulled from GitHub&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;rchive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;trip-components&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;rl&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ttps:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;releases&#x2F;download&#x2F;v4.1.0&#x2F;ball2box.tar.xz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ha256&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; 9&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;71b4a47bda0aa3f0bc6e1766b61eb848d0e10156505fef1f66531ac375bd5d4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;rl&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ttps:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;dulvui&#x2F;ball2box&#x2F;350a39a4eabc989145d22fbe0be0b4ae69033c71&#x2F;flatpak&#x2F;org.simondalvai.ball2box.desktop&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ha256&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; 6&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;a6d1d14649730dc3c61ce8c62baed9d2b8f2c71c801b1a8420275361bdff2e1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;rl&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ttps:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;dulvui&#x2F;ball2box&#x2F;350a39a4eabc989145d22fbe0be0b4ae69033c71&#x2F;flatpak&#x2F;org.simondalvai.ball2box.appdata.xml&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ha256&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;4aa1c9d9f3091c0be44269f591589bf5fc181c172a06f6882981345331f9552&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ype&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ile&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;con-256.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here the links to the Github repositories, where you can find the manifests&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;flathub&#x2F;org.simondalvai.ball2box&quot;&gt;&lt;strong&gt;Ball2Box&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;flathub&#x2F;org.simondalvai.pocket-broomball&quot;&gt;&lt;strong&gt;Pocket Broomball&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;appdata-xml&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#appdata-xml&quot; aria-label=&quot;Anchor link for: appdata-xml&quot;&gt;Appdata.xml&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The appdata file contains all other information of your app, like &lt;strong&gt;license, descriptions and screenshots&lt;&#x2F;strong&gt;.
This file should be &lt;strong&gt;upstream&lt;&#x2F;strong&gt; and placed in the repository of your app, if possible.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;xml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;?&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;xml&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; version&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; encoding&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;UTF-8&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;?&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;desktop-application&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;org.simondalvai.ball2box&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Ball2Box&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;developer_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Simon Dalvai&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;developer_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;launchable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;desktop-id&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;org.simondalvai.ball2box.desktop&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;launchable&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;project_license&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;AGPL-3.0-or-later&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;project_license&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;metadata_license&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;CC0-1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;metadata_license&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;summary&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Shoot the ball into the red box&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;summary&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;homepage&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;ball2box&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;bugtracker&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;issues&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;donation&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;https:&#x2F;&#x2F;simondalvai.org&#x2F;donate&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;vcs-browser&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;description&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Can you get all three stars on all levels?&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;120+ levels and more coming soon...&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;20+ different styled balls to collect&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Privacy friendly&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Offline game&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;Created with Godot Engine 3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;description&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;branding&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;color&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;primary&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; scheme_preference&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;light&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;#fdf6e3&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;color&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;color&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;primary&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; scheme_preference&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;dark&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;#002b36&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;color&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;branding&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;screenshots&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;default&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;dulvui&#x2F;ball2box&#x2F;570f236ac3d220d40e313e99859424d324386738&#x2F;metadata&#x2F;en-US&#x2F;images&#x2F;phoneScreenshots&#x2F;Android-1.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;dulvui&#x2F;ball2box&#x2F;570f236ac3d220d40e313e99859424d324386738&#x2F;metadata&#x2F;en-US&#x2F;images&#x2F;phoneScreenshots&#x2F;Android-2.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;dulvui&#x2F;ball2box&#x2F;570f236ac3d220d40e313e99859424d324386738&#x2F;metadata&#x2F;en-US&#x2F;images&#x2F;phoneScreenshots&#x2F;Android-3.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        https:&#x2F;&#x2F;raw.githubusercontent.com&#x2F;dulvui&#x2F;ball2box&#x2F;570f236ac3d220d40e313e99859424d324386738&#x2F;metadata&#x2F;en-US&#x2F;images&#x2F;phoneScreenshots&#x2F;Android-4.png&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;image&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;screenshot&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;screenshots&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;content_rating&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; type&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;oars-1.1&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt; &#x2F;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;releases&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;release&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; version&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;4.1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #93A1A1);&quot;&gt; date&lt;&#x2F;span&gt;&lt;span&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;2024-02-15&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;description&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;        &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;levels functionality&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;          &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;user interface refactoring&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;li&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;        &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ul&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;description&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;      &amp;lt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;span&gt;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;releases&#x2F;tag&#x2F;v4.1.0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;url&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;    &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;release&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;  &amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;releases&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;lt;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;component&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);&quot;&gt;&amp;gt;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here the links to the appdata files&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;blob&#x2F;main&#x2F;flatpak&#x2F;org.simondalvai.ball2box.appdata.xml&quot;&gt;&lt;strong&gt;Ball2Box&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;pocket-broomball&#x2F;blob&#x2F;main&#x2F;flatpak&#x2F;org.simondalvai.pocket-broomball.appdata.xml&quot;&gt;&lt;strong&gt;Pocket Broomball&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;desktop-file&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#desktop-file&quot; aria-label=&quot;Anchor link for: desktop-file&quot;&gt;Desktop file&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The desktop file finally defines how the app will appear in the OS, once installed.
Also this file should be &lt;strong&gt;upstream&lt;&#x2F;strong&gt; and placed in the repository of your app, if possible.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#!&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;&#x2F;usr&#x2F;bin&#x2F;env xdg-open&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;span&gt;Desktop Entry&lt;&#x2F;span&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;GenericName&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Comment&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; the&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; ball&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; into&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; the&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; red&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; box!&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Exec&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;r&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Icon&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;2&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;x&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Type&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;l&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;n&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Categories&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;=&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;G&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;e&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Here the links to the desktop files&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;blob&#x2F;main&#x2F;flatpak&#x2F;org.simondalvai.ball2box.desktop&quot;&gt;&lt;strong&gt;Ball2Box&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;pocket-broomball&#x2F;blob&#x2F;main&#x2F;flatpak&#x2F;org.simondalvai.pocket-broomball.desktop&quot;&gt;&lt;strong&gt;Pocket Broomball&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h3 id=&quot;256x256-px-icon&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#256x256-px-icon&quot; aria-label=&quot;Anchor link for: 256x256-px-icon&quot;&gt;256x256 px icon&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Finally, you&#x27;ll need an icon for the app, that should also be upstream.
It took me some time until I had the correct size of the icons with &lt;strong&gt;the right padding&lt;&#x2F;strong&gt;.
So, make sure that the icon follows the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.flathub.org&#x2F;docs&#x2F;for-app-authors&#x2F;metainfo-guidelines&#x2F;quality-guidelines&#x2F;#icon-size&quot;&gt;quality guidelines&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Here the links to the icons&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;flathub&#x2F;org.simondalvai.ball2box&#x2F;blob&#x2F;master&#x2F;icon-256.png&quot;&gt;&lt;strong&gt;Ball2Box&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;pocket-broomball&#x2F;blob&#x2F;main&#x2F;flatpak&#x2F;icon-256.png&quot;&gt;&lt;strong&gt;Pocket Broomball&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Note: The Ball2Box icon is placed in the Flathub repo, since I was not told in my PR to move it upstream.
But it is still recommended to have it upstream, like it is in Pocket Broomball.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;after-submission&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#after-submission&quot; aria-label=&quot;Anchor link for: after-submission&quot;&gt;After submission&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Once your pull request gets closed and the app is available on Flathub, you can &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;flathub.org&#x2F;login&quot;&gt;login&lt;&#x2F;a&gt; to Flathub and access some settings like &lt;strong&gt;app verification&lt;&#x2F;strong&gt; and the &lt;strong&gt;app listing quality&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;app-verification&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#app-verification&quot; aria-label=&quot;Anchor link for: app-verification&quot;&gt;App verification&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;To verify that you are the owner of the app, you can add a verification token to a .well-known&#x2F;org.flathub.VerifiedApps.txt file accessible on your website.
The &lt;strong&gt;domain must match the app-id&lt;&#x2F;strong&gt; used in the Manifest, like &lt;strong&gt;org.simondalvai.ball2box&lt;&#x2F;strong&gt; in my case.&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;.well-known&#x2F;org.flathub.VerifiedApps.txt&quot;&gt;simondalvai.org&#x2F;.well-known&#x2F;org.flathub.VerifiedApps.txt&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;If you have multiple apps, you can simply add multiple verification tokens to the file.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;app-listing-quality&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#app-listing-quality&quot; aria-label=&quot;Anchor link for: app-listing-quality&quot;&gt;App Listing Quality&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Flathub gives you also access to the app listing quality check.
To see that, you simply open the site of your game, while logged in.
Flathub has several &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.flathub.org&#x2F;docs&#x2F;for-app-authors&#x2F;metainfo-guidelines&#x2F;quality-guidelines&quot;&gt;quality guidelines&lt;&#x2F;a&gt; you have to follow.
If something is wrong, you can fix the issues and request a review.
Soon you&#x27;ll see if the problems have been resolved.&lt;&#x2F;p&gt;
&lt;p&gt;Here an example of the app listing quality check for &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;flathub.org&#x2F;apps&#x2F;org.simondalvai.pocket-broomball&quot;&gt;Pocket Broomball&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;img class=&quot;image-wide&quot; src=&quot;flathub-listing-quality.webp&quot; alt=&quot;Flathub app listing quality check&quot;&gt;  
&lt;h2 id=&quot;final-verdict&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-verdict&quot; aria-label=&quot;Anchor link for: final-verdict&quot;&gt;Final verdict&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Once an app is published and you are familiar with the processes, it is &lt;strong&gt;really easy&lt;&#x2F;strong&gt; to publish another one.
I also got quite some downloads (at least for me).
Currently both have &lt;strong&gt;250+ downloads&lt;&#x2F;strong&gt; combined.
If I compare this numbers with App Stores like Google Play and Apple App Store, they are quite impressive!&lt;&#x2F;p&gt;
&lt;p&gt;And of course: &lt;strong&gt;more app stores, more visibility&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;If you want to see more details of the pull requests itself, here the links&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;flathub&#x2F;flathub&#x2F;pull&#x2F;4956&quot;&gt;&lt;strong&gt;Ball2Box&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;flathub&#x2F;flathub&#x2F;pull&#x2F;5062&quot;&gt;&lt;strong&gt;Pocket Broomball&lt;&#x2F;strong&gt;&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Open sourcing your games as solo game developer - a game changer</title>
          <pubDate>Thu, 22 Feb 2024 21:22:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/open-source-games/</link>
          <guid>https://simondalvai.org/blog/open-source-games/</guid>
          <description xml:base="https://simondalvai.org/blog/open-source-games/">&lt;p&gt;In this post I would like to show &lt;strong&gt;what impact&lt;&#x2F;strong&gt; open sourcing my games had and &lt;strong&gt;why&lt;&#x2F;strong&gt; you should consider open sourcing your game too.&lt;&#x2F;p&gt;
&lt;p&gt;I already presented at &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;sfscon-2023-fdroid&#x2F;&quot;&gt;SFSCON 2023&lt;&#x2F;a&gt; what similar effect publishing my games on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;f-droid.org&#x2F;&quot;&gt;F-Droid&lt;&#x2F;a&gt; had on my games.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;more-visibility&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#more-visibility&quot; aria-label=&quot;Anchor link for: more-visibility&quot;&gt;More visibility&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Having games open sourced, gives you a lot of visibility on Github or your favorite git platform.
Your repo might pop up on &lt;strong&gt;online searches&lt;&#x2F;strong&gt; or even Github&#x27;s &lt;strong&gt;discovery section&lt;&#x2F;strong&gt;.
This brings you quality users and potential contributors.&lt;&#x2F;p&gt;
&lt;p&gt;Besides that, you can add your game to many &lt;strong&gt;awesome lists or websites&lt;&#x2F;strong&gt; that feature Open Source.
Here, a list of the few games I&#x27;ve got listed in:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;f-droid.org&quot;&gt;f-droid.org&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;fossdroid.com&quot;&gt;fossdroid.com&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;godotengine&#x2F;awesome-godot&quot;&gt;github.com&#x2F;godotengine&#x2F;awesome-godot&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;offa&#x2F;android-foss&quot;&gt;github.com&#x2F;offa&#x2F;android-foss&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;More visibility means &lt;strong&gt;more downloads&lt;&#x2F;strong&gt;, which bring to a &lt;strong&gt;higher ranking&lt;&#x2F;strong&gt; on game distribution platforms.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;quality-feedback&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#quality-feedback&quot; aria-label=&quot;Anchor link for: quality-feedback&quot;&gt;Quality feedback&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Getting feedback from users is quite hard.
Even harder is getting &lt;em&gt;good&lt;&#x2F;em&gt; feedback.
In my experience, this is the &lt;strong&gt;most drastic change&lt;&#x2F;strong&gt; you&#x27;ll see, when open sourcing your games.&lt;&#x2F;p&gt;
&lt;p&gt;This will change drastically, when you open source your game.
Because more &lt;strong&gt;technical people&lt;&#x2F;strong&gt; will see your games and they cannot only describe the bug or problem much better, but can also give suggestions on how to fix it.
This helps a lot, especially as a solo game developer, where you might not have much time to test all parts of your game, each time you make changes.
I also got a lot of feedback through e-mail, since I open sourced my games.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;be-different-be-one-of-a-few&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#be-different-be-one-of-a-few&quot; aria-label=&quot;Anchor link for: be-different-be-one-of-a-few&quot;&gt;Be different, be one of a few&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Given the scarcity of Open Source games, your game will be &lt;strong&gt;one of a few&lt;&#x2F;strong&gt; thousands instead of millions.
It is true that Open Source has a small audience, but there are still a lot of people out there caring for Open Source.&lt;&#x2F;p&gt;
&lt;p&gt;If you use &lt;strong&gt;donation&lt;&#x2F;strong&gt; platforms, this people will also be more open to support you, since they understand better your situation.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;better-portfolio&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#better-portfolio&quot; aria-label=&quot;Anchor link for: better-portfolio&quot;&gt;Better portfolio&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Letting other people see your code could be intimidating.
They might feel their code is not a good enough or feel afraid of critics.
Don&#x27;t worry, nobody will point fingers at you or comparing your code with the Linux Kernel code.&lt;&#x2F;p&gt;
&lt;p&gt;But whenever you want to impress someone, showing your source code and your ability to use git, it might be really handy.
So landing a new &lt;strong&gt;job&lt;&#x2F;strong&gt; or a project as freelancer, will be easier with an active [your favorite git platform] profile.&lt;&#x2F;p&gt;
&lt;p&gt;This applies to any software related work, not only games.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;licenses&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#licenses&quot; aria-label=&quot;Anchor link for: licenses&quot;&gt;Licenses&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I won&#x27;t get to deep into licenses, since it is a complex subject (and I&#x27;m not a lawyer).&lt;br &#x2F;&gt;
But here I want to share my experience and knowledge with you.
It is important to know that &lt;strong&gt;code&lt;&#x2F;strong&gt; and &lt;strong&gt;assets&lt;&#x2F;strong&gt; should have different type of licenses.
The most common software licenses are &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;GPL-3.0-or-later.html&quot;&gt;GPL&lt;&#x2F;a&gt; or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;MIT.html&quot;&gt;MIT&lt;&#x2F;a&gt; and for assets the mostly used licenses are Creative Commons license as the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;CC0-1.0.html&quot;&gt;CC0-1.0&lt;&#x2F;a&gt;, &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;CC-BY-4.0.html&quot;&gt;CC-BY-4.0&lt;&#x2F;a&gt; or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;CC-BY-SA-4.0.html&quot;&gt;CC-BY-4.0&lt;&#x2F;a&gt;.
Here you can find some &lt;strong&gt;tools&lt;&#x2F;strong&gt; to find a license for your assets that fits your needs&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;choosealicense.com&#x2F;&quot;&gt;choosealicense.com&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;chooser-beta.creativecommons.org&quot;&gt;chooser-beta.creativecommons.org&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h3 id=&quot;copyleft&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#copyleft&quot; aria-label=&quot;Anchor link for: copyleft&quot;&gt;Copyleft&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;I chose the copyleft &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;AGPL-3.0-or-later.html&quot;&gt;AGPL-v3-or-later&lt;&#x2F;a&gt; for my code and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;CC-BY-SA-4.0.html&quot;&gt;CC-BY-SA-4.0&lt;&#x2F;a&gt; for my assets.
This are copyleft licenses, that means that you are free to study, use, modify, share and that all derivates keep the same license.
The AGPL has a special clause about distributing code over network.
So technically if a &lt;strong&gt;cloud gaming&lt;&#x2F;strong&gt; provider wants to distribute my games, he would have to share the code with the users.
This would not be required with the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;GPL-3.0-or-later.html&quot;&gt;GPL-v3-or-later&lt;&#x2F;a&gt; license.
But as said before, I&#x27;m not a lawyer and this are my personal thoughts.
Do your research or get a lawyers advice, if needed.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;permissive&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#permissive&quot; aria-label=&quot;Anchor link for: permissive&quot;&gt;Permissive&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Some might prefer permissive licenses as &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;MIT.html&quot;&gt;MIT&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;spdx.org&#x2F;licenses&#x2F;CC-BY-4.0.html&quot;&gt;CC-BY-4.0&lt;&#x2F;a&gt;
This licenses give the user the same rights, but only require attribution and don&#x27;t require sharing the modified code, when distributed.
That means that someone might simply take your game, modify and release it, without having to share the modifications.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;contributing-to-open-source-ecosystem&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#contributing-to-open-source-ecosystem&quot; aria-label=&quot;Anchor link for: contributing-to-open-source-ecosystem&quot;&gt;Contributing to Open Source Ecosystem&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The Open Source world is already huge and well known.
But this doesn&#x27;t really apply to the &lt;strong&gt;gaming industry&lt;&#x2F;strong&gt;, where Open Source games are still quite rare.
In my personal opinion, this would make the gaming scene a better world, where game developers can learn from each other and improve games.
Or simply imagine being able to see the code of your &lt;strong&gt;favorite game&lt;&#x2F;strong&gt;, and being able to &lt;strong&gt;use, study, modify and share&lt;&#x2F;strong&gt; it!&lt;&#x2F;p&gt;
&lt;p&gt;If you believe in Open Source Software, &lt;strong&gt;be the change&lt;&#x2F;strong&gt; the gaming industry needs: make your games Open Source!&lt;&#x2F;p&gt;
&lt;h2 id=&quot;can-i-still-sell-my-games&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#can-i-still-sell-my-games&quot; aria-label=&quot;Anchor link for: can-i-still-sell-my-games&quot;&gt;Can I still sell my games?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;After all this, some might have the question if they still can sell their game.
And the answer is &lt;strong&gt;yes!&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;p&gt;Being open source doesn&#x27;t restrict you from monetizing your games.
There are many games and apps that are open source, available for free on F-Droid or other platforms but sold for money on Play Store, App Store or Steam.&lt;br &#x2F;&gt;
The best example that comes to my mind is &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;mindustrygame.github.io&#x2F;&quot;&gt;Mindustry&lt;&#x2F;a&gt; sold on Steam for 9,99$ (~15k reviews) but open source and available for free on all other platforms.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Create portals in Godot with _integrate_forces</title>
          <pubDate>Sun, 14 Jan 2024 17:48:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-portals/</link>
          <guid>https://simondalvai.org/blog/godot-portals/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-portals/">&lt;p&gt;My 3D Godot game &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;ball2box&#x2F;&quot;&gt;Ball2Box&lt;&#x2F;a&gt; needs some variety, so I created some portals for new levels.
This was not trivial to realize, as expected, and still needs some fine-tuning.
But the proof of concept finally works now, and it revealed quite easy to realize, if using the correct Godot functions.&lt;&#x2F;p&gt;
&lt;p&gt;Note: These are not portals like you might know from the game &quot;Portal&quot;, where you can see through the portal to the other side.
These portals simply teleport a moving body from one point to another.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;first-attempts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#first-attempts&quot; aria-label=&quot;Anchor link for: first-attempts&quot;&gt;First attempts&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The goal of the game is to get the ball into the box with only one shot.
If the attempt fails, the ball gets reset to its initial position.
So technically, I already had a &quot;teleport&quot; of the ball from its final position to the initial position.&lt;&#x2F;p&gt;
&lt;p&gt;Here, the old code of the &quot;reset to initial position&quot; function.
It simply changes the mode of the RigidBody to static, so it can be moved by changing the translation Vector.
Then it also resets all velocity and rotations, to make sure the ball remains still.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends RigidBody&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name Ball&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# ...omitted code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func reset() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    mode = RigidBody.MODE_STATIC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    translation = initial_position&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    linear_velocity = Vector3.ZERO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    angular_velocity = Vector3.ZERO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    rotation = Vector3.ZERO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course I ignored the warnings about changing game physics outside the physic process, because well, it worked.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;integrate-forces-the-forgotten-solution&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#integrate-forces-the-forgotten-solution&quot; aria-label=&quot;Anchor link for: integrate-forces-the-forgotten-solution&quot;&gt;_integrate_forces(), the forgotten solution&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Obviously, I thought this would work also for portals, where the ball gets teleported without resting the velocity and rotation.
After a few attempts for making it work, I tried searching the web, and luckily found some hint on using &lt;strong&gt;_integrate_forces&lt;&#x2F;strong&gt;.&lt;br &#x2F;&gt;
Surely somehow it would have worked without it, after banging my head for some hours, but using this function was the correct way.&lt;&#x2F;p&gt;
&lt;p&gt;The documentation of the _integrate_forces function writes&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;Called&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; during&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; physics&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; processing,&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; allowing&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; you&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; to&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; read&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; safely&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; modify&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; the&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; simulation&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; state&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; for&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; the&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; object.&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;strong&gt;Safely&lt;&#x2F;strong&gt; is here the keyword!
It means that there will be no strange glitches or non expected movements&lt;&#x2F;p&gt;
&lt;p&gt;Here the final working code, that not only teleports the ball from portal to portal, but also to its initial position.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends RigidBody&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name Ball&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var do_teleport:bool = false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var do_reset:bool = false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var do_static:bool = false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var initial_position:Transform&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var next_transform:Transform&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func teleport(p_transform:Transform) -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	next_transform = p_transform&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	do_teleport = true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func teleport_to_initial() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	do_reset = true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _integrate_forces(state:PhysicsDirectBodyState) -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	# change the mode to static on the next iteration&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	# otherwise ball doesn&amp;#39;t move to new position&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	if do_static:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		do_static = false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		mode = RigidBody.MODE_STATIC&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	if do_teleport:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		state.transform = next_transform&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		do_teleport = false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	if do_reset:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		state.transform = initial_position&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		state.angular_velocity = Vector3.ZERO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		state.linear_velocity = Vector3.ZERO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		rotation = Vector3.ZERO&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		do_reset = false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		do_static = true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An important difference here, is that instead of moving the ball directly, a flag gets set.
The actual movement happens then during the next _integrate_forces step.&lt;&#x2F;p&gt;
&lt;p&gt;For completion, here the code where the teleport function gets called, with the transform variable of the corresponding portal.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _on_Portal1_ball_entered(ball:Ball) -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	ball.teleport(portal2.transform)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;After some refactoring of &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;pocket-broomball&#x2F;&quot;&gt;Pocket Broomball&lt;&#x2F;a&gt;, I found out that I already used _integrate_forces there to move the ball.
So, I was already sitting on the solution, but forgot about it, as usual.&lt;&#x2F;p&gt;
&lt;p&gt;Find the full documentation of _integrate_forces &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;classes&#x2F;class_rigidbody3d.html#class-rigidbody3d-private-method-integrate-forces&quot;&gt;here&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The full source code of Ball2box is available on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&quot;&gt;Github&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;ball2box&quot;&gt;Codeberg&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Create Apple Developer Certificate on Linux</title>
          <pubDate>Sun, 10 Dec 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/dev-cert-linux/</link>
          <guid>https://simondalvai.org/blog/dev-cert-linux/</guid>
          <description xml:base="https://simondalvai.org/blog/dev-cert-linux/">&lt;p&gt;To upload a app to the App Store, you need to create a Developer Certificate.
The official Apple guide shows you how to do it easily with a Mac device in its official &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.apple.com&#x2F;help&#x2F;account&#x2F;create-certificates&#x2F;create-a-certificate-signing-request&quot;&gt;documentation&lt;&#x2F;a&gt;.
But it can be done also without a Mac, using a Linux System, following &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gist.github.com&#x2F;jcward&#x2F;d08b33fc3e6c5f90c18437956e5ccc35&quot;&gt;this guide&lt;&#x2F;a&gt; of a Github user.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-do-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-to-do-it&quot; aria-label=&quot;Anchor link for: how-to-do-it&quot;&gt;How to do it&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ol&gt;
&lt;li&gt;Generate a private key and certificate signing request:
Firs create a private key with openssl&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; genrsa&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;out&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2048&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then you can create a Certificate Sign Request, shortly CSR, using the previously generated private key.&lt;br &#x2F;&gt;
Note: change &quot;info@simondalvai.org&quot; and &quot;Simon Dalvai&quot; with your values.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; req&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;new&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;out&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.csr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;subj&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&#x2F;emailAddress=info@simondalvai.org, CN=Simon Dalvai, C=IT&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;p&gt;Upload the CSR to apple at: https:&#x2F;&#x2F;developer.apple.com&#x2F;account&#x2F;ios&#x2F;certificate&#x2F;create
Choose Production -&amp;gt; App Store and Ad Hoc&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Download the resulting distribution.cer, and convert it to .pem format:&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; x509&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;inform&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; der&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.cer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;out&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.pem&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;Download Apple&#x27;s Worldwide developer cert from &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.apple.com&#x2F;certificateauthority&#x2F;&quot;&gt;Apple&#x27;s certificates website&lt;&#x2F;a&gt; and convert it to pem:&lt;br &#x2F;&gt;
Note: Here Worldwide Developer Relations - G4 (expiring 12&#x2F;10&#x2F;2030) is used.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;wget&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; https:&#x2F;&#x2F;www.apple.com&#x2F;certificateauthority&#x2F;AppleWWDRCAG4.cer&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; x509&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; AppleWWDRCAG4.cer&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;inform&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; DER&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;out&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; AppleWWDRCAG4.pem&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;outform&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; PEM&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;5&quot;&gt;
&lt;li&gt;Convert your cert plus Apple&#x27;s cert to p12 format (choose a password for the .p12).&lt;br &#x2F;&gt;
Note: use -legacy if using opensssl v3.x . Found on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;70431528&#x2F;mac-verification-failed-during-pkcs12-import-wrong-password-azure-devops&quot;&gt;StackOverflow&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;openssl&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; pkcs12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;export&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;legacy&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;out&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.p12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;inkey&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.key&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;in&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.pem&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;certfile&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; AppleWWDRCAG4.pem&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;6&quot;&gt;
&lt;li&gt;Finally, update any Provisioning Profile with the new cert, and download them from dev portal.
Now you can also sign any Provisioning Profiles with the new certificate and use them to release apps.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;h2 id=&quot;use-in-ci-cd-like-github-actions&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#use-in-ci-cd-like-github-actions&quot; aria-label=&quot;Anchor link for: use-in-ci-cd-like-github-actions&quot;&gt;Use in CI&#x2F;CD like Github Actions&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The Developer Certificate and Provisioning Profile can be imported in any CI&#x2F;CD system, like Github Actions.
But most CI&#x2F;CD systems don&#x27;t support binary files, so the conversion to base64 is needed.&lt;&#x2F;p&gt;
&lt;ol&gt;
&lt;li&gt;Create base64 of distribution.p12
Now you can prepare the Developer Certificate for the Github Action.&lt;br &#x2F;&gt;
Note: use &lt;code&gt;-w 0&lt;&#x2F;code&gt; to prevent new lines in the resulting base64 string.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;base64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.p12&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 0&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; &amp;gt;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.base64&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;
&lt;p&gt;Add distribution.base64 content to your CI&#x2F;CD systems secrets&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;
&lt;p&gt;Recreate the file in its binary format&lt;&#x2F;p&gt;
&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;shellscript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;echo&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;$&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;BUILD_CERTIFICATE_BASE64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; |&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; base64&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;-decode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; distribution.p12&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The same steps work with any binary file, like the Provisioning Profile.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>[Talk] SFSCON 2023: F-Droid - The place for your FOSS Apps</title>
          <pubDate>Fri, 17 Nov 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/sfscon-2023-fdroid/</link>
          <guid>https://simondalvai.org/blog/sfscon-2023-fdroid/</guid>
          <description xml:base="https://simondalvai.org/blog/sfscon-2023-fdroid/">&lt;p&gt;Also this year I had a talk at &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.sfscon.it&#x2F;&quot;&gt;SFSCON 2023&lt;&#x2F;a&gt; about F-Droid.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;abstract&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#abstract&quot; aria-label=&quot;Anchor link for: abstract&quot;&gt;Abstract&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;On F-Droid you can find thousands of FOSS apps and games for Android.
F-Droid brings you visibility in the FOSS community that will provide great feedback, open issues and eventually contribute to your FOSS project.&lt;&#x2F;p&gt;
&lt;p&gt;This presentation is about my personal experience with my games Ball2Box, Pocket Broomball and Sn4ke published on F-Droid. I will show you what F-Droid is, how it works and the steps needed to submit your project.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;youtube-video&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#youtube-video&quot; aria-label=&quot;Anchor link for: youtube-video&quot;&gt;Youtube Video&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here you can find the video of my talk on YouTube &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;live&#x2F;PoaUQyaQVJE?t=4986&quot;&gt;https:&#x2F;&#x2F;www.youtube.com&#x2F;live&#x2F;PoaUQyaQVJE?t=4986&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;h2 id=&quot;slides&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#slides&quot; aria-label=&quot;Anchor link for: slides&quot;&gt;Slides&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here you can find the slides &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;sfscon-2023-fdroid&#x2F;sfscon-2023-simon-dalvai-fdroid.pdf&quot;&gt;sfscon-2023-simon-dalvai-fdroid.pdf&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Custom Resources in Godot Engine 4.x</title>
          <pubDate>Mon, 16 Oct 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-custom-resources/</link>
          <guid>https://simondalvai.org/blog/godot-custom-resources/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-custom-resources/">&lt;h2 id=&quot;godot-resources-in-a-nutshell&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#godot-resources-in-a-nutshell&quot; aria-label=&quot;Anchor link for: godot-resources-in-a-nutshell&quot;&gt;Godot Resources in a nutshell&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Godot has a lot cool features built in that make game development a joyful ride.
One of this awesome features are &lt;strong&gt;Custom Resources&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Technically all the parts of Godot that save some data extend the Resource class.
They are data containers that can contain all sort of data: translations, audio, textures and much more.
This are all built-in Resources, but you can create also you own Custom Resources, that help you defining data structures and bring a lot of other features.&lt;&#x2F;p&gt;
&lt;p&gt;I learned about Custom Resources quite late, since I was able to all my data related problems with Dictionaries and JSON files.
But now I work on bigger projects, like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;futsal-manager&#x2F;&quot;&gt;Futsal Manager&lt;&#x2F;a&gt; where I need a lot of data.
In such complex projects Custom Resources are a big game changer and make the development easier, with less errors and faster development.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;custom-resources&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#custom-resources&quot; aria-label=&quot;Anchor link for: custom-resources&quot;&gt;Custom Resources&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;You can create your own Custom Resources simply by creating an empty Script file, giving it a class_name and extending it with the Resources class.
Then you can define some variables, enums, constants and methods like in this example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name MyResource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;signal such_signal&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;enum SuchEnum { Hello, Custom, Resources }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var name:String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var id:int = 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var values:Array[int]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var enumValue:SuchEnum&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func get_sum() -&amp;gt; int:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    var sum:int = 0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    for value in values:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        sum += value&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    return sum&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func special_effect() -&amp;gt; void:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    if randi() % 10 == 1:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;        such_signal.emit()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now you can create a variable of the type MyResource and you get the functions and variables name with the editors autocomplete.
So you are sure that you always use the correct variable name.
With Dictionaries instead, you have to remember the names of the keys.&lt;br &#x2F;&gt;
By using the @export annotation you can modify all your resources directly in the editor.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;save-and-load&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#save-and-load&quot; aria-label=&quot;Anchor link for: save-and-load&quot;&gt;Save and load&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Another cool feature is the built-in load and save to disk functionality.
So you can replace all your JSON files with built-in Custom Resources.&lt;br &#x2F;&gt;
Note: Only variables with @export annotation get saved to disk.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;WARNING&lt;&#x2F;strong&gt; RESOURCES CAN EXECUTE MALICOUS CODE&lt;br &#x2F;&gt;
As long as this &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;godotengine&#x2F;godot-proposals&#x2F;issues&#x2F;4925&quot;&gt;Github issue&lt;&#x2F;a&gt;
is open, resources should not be considered as a safe way to save data.&lt;&#x2F;p&gt;
&lt;p&gt;Here an example:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# create variable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var my_resource:MyResource = MyResource.new()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# assign values&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;my_resource.name = &amp;quot;Hello Resources&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;my_resource.values = [0, 3, 12]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# save it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;ResourceSaver.save(my_resource, &amp;quot;res:&#x2F;&#x2F;my_resource.tres&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# load it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var my_resource_from_disk:MyResource = load(&amp;quot;res:&#x2F;&#x2F;my_resource.tres&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# prints &amp;quot;Hello Resources&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;print(my_resource_from_disk.name)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# prints &amp;quot;15&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;print(my_resource_from_disk.sum())&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Good to know is that during runtime you can write resources only into the &lt;code&gt;user:&#x2F;&#x2F;&lt;&#x2F;code&gt; directory.
Files from the &lt;code&gt;res:&#x2F;&#x2F;&lt;&#x2F;code&gt; directory are read only.
So if you want to save data the user modified or created, you need to save them into the &lt;code&gt;user:&#x2F;&#x2F;&lt;&#x2F;code&gt; directory.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;complex-data-structures&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#complex-data-structures&quot; aria-label=&quot;Anchor link for: complex-data-structures&quot;&gt;Complex data structures&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;With custom resources you can create all kind of data you can imagine.
So you can use a created resource in another one.
So for example if you create a football team, you can split the team and its players with its own resources.&lt;&#x2F;p&gt;
&lt;p&gt;Here some code of my Futsal Manager game:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# team.gd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name Team&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var name:String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var line_up:LineUp&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var prestige:int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var budget:int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var salary_budget:int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var players:Array[Player]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# ...code goes on here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# player.gd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;class_name Player&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Resource&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var id:int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var price:int&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var name:String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var surname:String&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;@export var birth_date:Dictionary&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;# ...code goes on here&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;So with this two resources, I can define the &lt;code&gt;players&lt;&#x2F;code&gt; variable in teams that is an Array of Players and can contain only variables of the type &lt;code&gt;Player&lt;&#x2F;code&gt;.
This makes the code type safe and gives you code autocompletion in the editor.
Theres is no limit on how many Resources and Sub-resources you create.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;tres-vs-res&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#tres-vs-res&quot; aria-label=&quot;Anchor link for: tres-vs-res&quot;&gt;.tres vs .res&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Resources can be saved in two file formats &lt;strong&gt;.tres&lt;&#x2F;strong&gt; that are version-control-friendly and human readable.&lt;br &#x2F;&gt;
&lt;strong&gt;.res&lt;&#x2F;strong&gt; files instead are binary files and have better speed and compression.
So depending on what data your store, you might prefer one or the other.
It makes sense to save users data as .res files for performance and to save disk space.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;further-readings&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#further-readings&quot; aria-label=&quot;Anchor link for: further-readings&quot;&gt;Further readings&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This was just my personal experience and knowledge about Godot&#x27;s Custom Resources.
They surely can do even more interesting stuff and there is a lot of other information about them on the web.&lt;&#x2F;p&gt;
&lt;p&gt;Here you can read the official Godot &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;tutorials&#x2F;scripting&#x2F;resources.html&quot;&gt;documentation&lt;&#x2F;a&gt; on how to use Resources and what features they bring.&lt;br &#x2F;&gt;
And here you can find the official &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;docs.godotengine.org&#x2F;en&#x2F;stable&#x2F;classes&#x2F;class_resource.html#class-resource&quot;&gt;class reference&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Condor</title>
          <pubDate>Sat, 23 Sep 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/games/condor/</link>
          <guid>https://simondalvai.org/games/condor/</guid>
          <description xml:base="https://simondalvai.org/games/condor/">&lt;p&gt;App to organize the Italian Fantasy Football game &quot;Fantacalcio&quot; auction.&lt;&#x2F;p&gt;
&lt;p&gt;More info and first release coming soon...&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Create non-game apps with Godot Engine</title>
          <pubDate>Mon, 18 Sep 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-apps/</link>
          <guid>https://simondalvai.org/blog/godot-apps/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-apps/">&lt;p&gt;The main target of the Godot Engine are game developers.
But Godot&#x27;s easy workflow and functional UI elements, makes it also a good fit for non-game applications.
There are already some out there you may know, like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;Orama-Interactive&#x2F;Pixelorama&quot;&gt;Pixelorama&lt;&#x2F;a&gt;, an Open Source 2D sprite editor.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;a-condor-is-born&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#a-condor-is-born&quot; aria-label=&quot;Anchor link for: a-condor-is-born&quot;&gt;A Condor is born&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Recently I also started creating an application made with Godot Engine, named &quot;Condor&quot;.
It is a mobile and desktop app for managing the Italian Fantasy Football &quot;Fantacalcio&quot; auction.
If you never heard of &quot;Fantacalcio&quot; or &quot;Fantasy Football&quot;, it is a game where you compete with a group of friends, by buying real football players and earning points in each match day, depending on the real life performance of the football players.
You can read more about it on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Fantasy_football_(association)&quot;&gt;Wikipedia&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The name &quot;Condor&quot; derives from the nickname &quot;il condor&quot; of &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Adriano_Galliani&quot;&gt;Adriano Galliani&lt;&#x2F;a&gt;.
He gained the name by his strategy of buying football players during the last hours of the transfer market, to get better conditions, because teams want to get rid of some players they where not able to sell yet.
Since this application also brings a timer for the auction, it gets more intense and interesting until the last moments.
So, some might buy a player during the last seconds of the auction and become a condor too.&lt;&#x2F;p&gt;
&lt;p&gt;There are already some auction apps out there, but none of them (at least as I found) is Open Source and available for Linux, without ads and tracking.
You can find the source code on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;condor&quot;&gt;Github&lt;&#x2F;a&gt; or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;codeberg.org&#x2F;dulvui&#x2F;condor&quot;&gt;Codeberg&lt;&#x2F;a&gt; as usual.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;first-impressions&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#first-impressions&quot; aria-label=&quot;Anchor link for: first-impressions&quot;&gt;First impressions&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;For now I really enjoy creating apps with the Godot Engine, since it is really easy and fast to create complex UIs.
It is perfect for fast prototyping and Godot&#x27;s Scene&#x2F;Node architecture with signals, makes it quite easy to understand.
Since the whole Engine is Open Source, you can find a lot of code and sample project out there.
I don&#x27;t have much experience with other cross-platform development kits like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;flutter.dev&#x2F;&quot;&gt;Flutter&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
If someone has experience with Flutter and Godot, please let me know, if Flutter or any other cross-platform development kit would be a better fit or not.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;websockets-and-hetzner-cloud&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#websockets-and-hetzner-cloud&quot; aria-label=&quot;Anchor link for: websockets-and-hetzner-cloud&quot;&gt;WebSockets and Hetzner Cloud&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;One goal of the application is also to make it possible to follow the auction remotely.
So, all participants can see all the football players someone bought during the auction, the remaining budget, still available players and participate at the auction with the auction timer.&lt;&#x2F;p&gt;
&lt;p&gt;To implement this features, I used a simple WebSocket client&#x2F;server architecture and the cheapest Hetzner cloud server for around 4€ per month.
I used Godot&#x27;s official WebSocket chat demo project you can find on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;godotengine&#x2F;godot-demo-projects&#x2F;tree&#x2F;master&#x2F;networking&#x2F;websocket_chat&quot;&gt;Github&lt;&#x2F;a&gt;.
Running the server for 3 days costs me around 0,30€.
Of course this setup is just for personal use and would (probably) not work for many players.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;testing-in-real-auction&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#testing-in-real-auction&quot; aria-label=&quot;Anchor link for: testing-in-real-auction&quot;&gt;Testing in real auction&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I used the application in one real life auction and it nearly worked perfectly.
Except some synchronization issues with the remote players, since there is no resync implemented yet, if the connection fails.
So, someone misses all the players that are sold, during the disconnection.&lt;&#x2F;p&gt;
&lt;img class=&quot;image image-wide&quot; src=&quot;condor.webp&quot; alt=&quot;Admin view of the application &#x27;Condor&#x27;&quot;&gt;  
&lt;p&gt;Here you can see the admin view in action (I&#x27;m not a designer).&lt;br &#x2F;&gt;
On the left top, you can see all players list and the sell&#x2F;buy history is visible in the left bottom corner.
On the right from top to down: the active player with the auction controls and then the overview of all teams.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;next-steps&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#next-steps&quot; aria-label=&quot;Anchor link for: next-steps&quot;&gt;Next steps&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Since WebSockets require a constant connection with a server or a host, WebRTC might be a better fit for this scenario.
With WebRTC you still need a server, but only to match the peers together.
Once they are connected, the communication is directly peer2peer.&lt;&#x2F;p&gt;
&lt;p&gt;Then the UI needs of course a huge redesign and more appealing and modern graphical elements.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;release-date&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#release-date&quot; aria-label=&quot;Anchor link for: release-date&quot;&gt;Release date&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This year I will use the app only internally for my own Fantacalcio league, but I plan to release it to the public for the next season 2024&#x2F;2025.
So, the application will be released for mobile, desktop and web during summer 2024 (hopefully).&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-verdict&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-verdict&quot; aria-label=&quot;Anchor link for: final-verdict&quot;&gt;Final verdict&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I really enjoyed creating this application, since I learned a lot, especially on how to create stable und working UIs in Godot.
It was also my first online multiplayer experience with Godot.
So, if you already know how to use the Godot Engine or want to learn it, even for non-game applications, give it a try.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Thank you Debian and happy Birthday!</title>
          <pubDate>Thu, 17 Aug 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/thank-you-debian/</link>
          <guid>https://simondalvai.org/blog/thank-you-debian/</guid>
          <description xml:base="https://simondalvai.org/blog/thank-you-debian/">&lt;p&gt;Happy 30th Birthday Debian!&lt;br &#x2F;&gt;
With this blog post I want to thank all Debian contributors, volunteers and people involved in the project.
I&#x27;ve been using a Debian based Distro since the first day of my Linux journey around 2013. I started with Ubuntu, then Linux Mint, followed by Manjaro (the only not Debian, I&#x27;ve been using for some time) and again Linux Mint, always with XFCE.&lt;br &#x2F;&gt;
And of course, a lot of Distro hopping in between, but these are the ones, I&#x27;ve used for at least one month.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;kde-plasma-3&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#kde-plasma-3&quot; aria-label=&quot;Anchor link for: kde-plasma-3&quot;&gt;KDE Plasma &amp;lt;3&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;But this year, I discovered the KDE Plasma Desktop Environment.
It feels like XFCE, with all the customizations I normally did manually, but already built-in out of the box.&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Like a &lt;strong&gt;good clipboard manager&lt;&#x2F;strong&gt;, that automatically &lt;strong&gt;ignores copied passwords&lt;&#x2F;strong&gt; from Passwords managers like KeepassXC.&lt;&#x2F;li&gt;
&lt;li&gt;The automatic &lt;strong&gt;remote host name in the title&lt;&#x2F;strong&gt; of KDE&#x27;s terminal application Konsole.
This is really handy, if you login to many remote servers and would like to remember which server you are logged in.
So you can do &lt;code&gt;rm -rf &#x2F;*&lt;&#x2F;code&gt; in the right place ;-)&lt;&#x2F;li&gt;
&lt;li&gt;And the last killer feature for me was the built-in battery limit option, that limits the charge of your laptop (might work only with Thinkpads, but I&#x27;m not sure).
So you can extend the life of your battery.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;And last but not least, KDE Plasma looks really beautiful and has a lot of really great own software.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-debian&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-debian&quot; aria-label=&quot;Anchor link for: why-debian&quot;&gt;Why Debian&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The reason why I chose Debian with KDE Plasma was, that it&#x27;s the only Distro I can surely trust that it will exist for many more years and that no company will overtake the project and close it&#x27;s source code or create some questionable subscription model.
Yes, I&#x27;m looking at you, Red Hat.
Then the latest movements in the Open Source world also just confirm, that it is better to trust a non-profit organization.
Sorry, but not sorry, HashiCorp.&lt;&#x2F;p&gt;
&lt;p&gt;All well known Debian based Distros, like KDE Neon or Kubuntu, have Canonical&#x27;s Snap package system pre-installed.&lt;br &#x2F;&gt;
Debian is the &lt;strong&gt;only&lt;&#x2F;strong&gt; Distro, that I&#x27;ve found, that doesn&#x27;t pre-implement Snap package system and only uses real Open Source Software.&lt;&#x2F;p&gt;
&lt;p&gt;And here, myself enjoying the beautiful city of Bari, Italy, with my favorite T-Shirt :-)&lt;br &#x2F;&gt;
&lt;img class=&quot;image&quot; src=&quot;debian-bari-2023.jpeg&quot; alt=&quot;Myself with my Debian T-Shirt in Bari, Italy.&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Happy birthday!&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Porting my libGDX games to Godot</title>
          <pubDate>Thu, 20 Jul 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/libgdx-to-godot/</link>
          <guid>https://simondalvai.org/blog/libgdx-to-godot/</guid>
          <description xml:base="https://simondalvai.org/blog/libgdx-to-godot/">&lt;p&gt;After using libGDX, since 2020 I create my games only with Godot Engine.
I find Godot easier and faster than libGDX.
There is also to say that libGDX is just a Java Framework and Godot is a full Engine.
I already wrote a &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;godot-vs-libgdx&#x2F;&quot;&gt;blog post&lt;&#x2F;a&gt; about libGDX vs Godot comparing the main differences and my experience with both.&lt;&#x2F;p&gt;
&lt;p&gt;Now I&#x27;ve decided that I will port my old games to Godot, since it might actually be the better way to keep my games up to date.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;my-motivations&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#my-motivations&quot; aria-label=&quot;Anchor link for: my-motivations&quot;&gt;My motivations&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Using libGDX every few months, to make a few changes or update some SDK or dependency is always a pain.
Especially for libGDX iOS games, because &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;MobiVM&#x2F;robovm&quot;&gt;robovm&lt;&#x2F;a&gt; is needed, to compile the Java code for iOS.
I spend hours to fix the dependency issues and end up with a setup that somehow works, but I don&#x27;t really understand how and why.
That repeats every few months.&lt;br &#x2F;&gt;
Of course, if I would learn gradle better I might be able to be much faster.
But I find it very hard learning things I barely use.
And this will be the last time I face a dependency version mismatch, gradle build errors and hours of cryptic debugging.&lt;&#x2F;p&gt;
&lt;p&gt;Another big motivator is that the Apple App Store removes all app that didn&#x27;t get an update in the last 2 years ( or is it 3? I found different articles with different years).
So anyway I would have to do an update at least every 2 years, even if nothing changes in the game.&lt;&#x2F;p&gt;
&lt;p&gt;I still need to say that libGDX is really great.
I enjoyed the time and learned a lot.
If you use it often and don&#x27;t target iOS, it&#x27;s a great and powerful framework.
But in my case, it&#x27;s better to say good bye.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;why-godot-engine&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#why-godot-engine&quot; aria-label=&quot;Anchor link for: why-godot-engine&quot;&gt;Why Godot Engine?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Godot is one of the most promising and growing Open Source Game Engine with a great community.
As said before, Godot is quite easy to learn.
It makes the maintenance of a game also much easier.
The only time you really need to take a step back and learn new things, is when a new major version comes out.&lt;&#x2F;p&gt;
&lt;p&gt;Not having to fight with gradle is also a big plus for me.
And the good thing is, if you like gradle, you can still use it for Android with Godot&#x27;s custom build feature.&lt;&#x2F;p&gt;
&lt;p&gt;Finding help online is also much easier, since there is a big community and really nice docs.
And it just works.
Exporting a game for Android, iOS, html, Desktop etc simply works out of the box.
No need for special tools or knowledge of other software than Godot.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-games-will-be-ported&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-games-will-be-ported&quot; aria-label=&quot;Anchor link for: what-games-will-be-ported&quot;&gt;What games will be ported?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;I will port for first &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;sn4ke&#x2F;&quot;&gt;Sn4ke&lt;&#x2F;a&gt; to Godot.
It is the game with most downloads and the game I spent most time to create it.
It&#x27;s also the only libGDX game I currently have on iOS.&lt;&#x2F;p&gt;
&lt;p&gt;After that I will port &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;whatcolor&#x2F;&quot;&gt;WhatColor&lt;&#x2F;a&gt;.
There I will also extend and improve the game with sound, more levels, tutorials etc...
It will then also be published for iOS.&lt;&#x2F;p&gt;
&lt;p&gt;Last and least, my very first game &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;color-shooter&#x2F;&quot;&gt;ColorShooter&lt;&#x2F;a&gt;.
I still don&#x27;t know if I will port this game, but maybe some nostalgia will motivate me to do so.
Anyway, if you see updates on this game, it will surely be made with Godot.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>How to not install LineageOS 20 on Pixel 5 in 2023</title>
          <pubDate>Sat, 08 Jul 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/install-lineageos-pixel5/</link>
          <guid>https://simondalvai.org/blog/install-lineageos-pixel5/</guid>
          <description xml:base="https://simondalvai.org/blog/install-lineageos-pixel5/">&lt;p&gt;I just bought a refurbished Pixel 5 to upgrade from my Samsung Galaxy S5.
The Samsung is still getting updates on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lineageos.org&#x2F;&quot;&gt;LineageOS&lt;&#x2F;a&gt; 18.1 and working fine for simple tasks, but I felt that it was time to change phone.
I looked for a while what phone I should buy, since I wanted a compact phone, so there were not many options.&lt;&#x2F;p&gt;
&lt;p&gt;A must have is LineageOS 20 support, so I found this awesome page &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;lineageosdevices.com&#x2F;&quot;&gt;lineageosdevices.com&lt;&#x2F;a&gt; where you can compare devices that can run the latest version.
So I found the Pixel 5, that is quite new (released 2020) and small (6 inches, but only 144.7 mm height).&lt;&#x2F;p&gt;
&lt;p&gt;The install process was not as simple as I taught, since I made some mistakes.&lt;br &#x2F;&gt;
With this blog post I will share what I did wrong and how to fix eventual boot loops or other problems.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;read-the-guide-really-do-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#read-the-guide-really-do-it&quot; aria-label=&quot;Anchor link for: read-the-guide-really-do-it&quot;&gt;Read the guide, really do it&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Read and follow carefully the official install guide&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;wiki.lineageos.org&#x2F;devices&#x2F;redfin&#x2F;install&quot;&gt;https:&#x2F;&#x2F;wiki.lineageos.org&#x2F;devices&#x2F;redfin&#x2F;install&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
It will prevent a lot of mistakes, if I would have read it more carefully I would have taken less time.
If you really follow the guide it will take you around 20 minutes to install it. It took me around 3 hours.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-went-wrong-fastboot-version&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-went-wrong-fastboot-version&quot; aria-label=&quot;Anchor link for: what-went-wrong-fastboot-version&quot;&gt;What went wrong - fastboot version&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Firstly I used an &lt;strong&gt;old fastboot version&lt;&#x2F;strong&gt;.
Debian&#x27;s fastboot version is a bit old, so you need to download fastboot from the official Android site&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;developer.android.com&#x2F;tools&#x2F;releases&#x2F;platform-tools#downloads&quot;&gt;https:&#x2F;&#x2F;developer.android.com&#x2F;tools&#x2F;releases&#x2F;platform-tools#downloads&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
The LineageOS guide also mentions this, but since I didn&#x27;t read the guide carefully, shit happened.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-went-wrong-twrp&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#what-went-wrong-twrp&quot; aria-label=&quot;Anchor link for: what-went-wrong-twrp&quot;&gt;What went wrong - TWRP&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Alongside LineageOS, I always install the TWRP custom recovery menu from&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;twrp.me&quot;&gt;https:&#x2F;&#x2F;twrp.me&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
For some reasons, when trying to temporarily boot TWRP on the Pixel 5, it always stayed stuck on the TWRP splash screen.
The first time I used the old fastboot version, but also after using the new one adn re-flashing the stock rom, I always had the same problem.&lt;br &#x2F;&gt;
So I installed the &lt;strong&gt;Lineage recovery menu&lt;&#x2F;strong&gt;, but also with no success.
My phone got stuck in several boot loops and I was not able to boot the stock rom.&lt;br &#x2F;&gt;
If you know how to fix this, please let me know.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-rescue-flash-the-stock-rom&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-rescue-flash-the-stock-rom&quot; aria-label=&quot;Anchor link for: the-rescue-flash-the-stock-rom&quot;&gt;The rescue - flash the stock rom&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;My phone was completely broken.
It didn&#x27;t boot the stock rom, recovery menu didn&#x27;t boot either.
Only the fastboot bootloader was still working.
If you encounter boot loops or other problems like me, a good solution is to flash the stock rom again.
You can flash it manually or you can use this amazing website, that will do all the work for you.&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;flash.android.com&#x2F;back-to-public&quot;&gt;https:&#x2F;&#x2F;flash.android.com&#x2F;back-to-public&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You need a Chrome browser to use it, so I installed Chromium and it worked fine.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-sprint&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-sprint&quot; aria-label=&quot;Anchor link for: final-sprint&quot;&gt;Final sprint&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;After flashing the stock rom I followed exactly the LineageOS guide, with the latest fastboot version and no TWRP but Lineage recovery menu.
Then finally after 3 hours and a lot of tears, LineageOS 20 booted correctly on my new Pixel 5.
This took me just around 20 minutes, so as usual, the best advice is to &lt;strong&gt;really read the docs&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;long-story-short&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#long-story-short&quot; aria-label=&quot;Anchor link for: long-story-short&quot;&gt;Long story short&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;ul&gt;
&lt;li&gt;Read the docs carefully&lt;&#x2F;li&gt;
&lt;li&gt;TWRP didn&#x27;t work for me&lt;&#x2F;li&gt;
&lt;li&gt;Use latest fastboot version&lt;&#x2F;li&gt;
&lt;li&gt;Flash stock rom to start from scratch&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
</description>
      </item>
      <item>
          <title>Upload a Godot HTML5 game to itch.io with Github Actions</title>
          <pubDate>Wed, 07 Jun 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-itchio-upload/</link>
          <guid>https://simondalvai.org/blog/godot-itchio-upload/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-itchio-upload/">&lt;p&gt;With the following two Github Actions you can export a Godot game to HTML and upload it to &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;itch.io&quot;&gt;itch.io&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;godot-html-export&quot;&gt;godot-html-export&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;itchio-butler-upload&quot;&gt;itchio-butler-upload&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;First you need to create a game on itch.io with all the needed information,
then a first build can be uploaded with this Github Action.&lt;br &#x2F;&gt;
With this simple action you can automate the upload on every push.
Of course the branch, game names etc. must be changed according to your needs.
Read the &lt;strong&gt;comments&lt;&#x2F;strong&gt; in the following action code to understand whats happening.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;tch.io upload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; define what triggers the action&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; in this case: on push if one of the files named in paths changes&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#B58900, #B58900);&quot;&gt;on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ush&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;aths&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;version-android&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;version-ios&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;.github&#x2F;workflows&#x2F;upload-itchio.yml&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; the directory where your game is&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;#&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; I always put the game inside a &amp;#39;game&amp;#39; folder&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  W&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ORKING_DIRECTORY&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;obs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;  d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;eploy&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; only run action, if pushed on prod branch&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;    #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; change or remove according to your needs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ithub.ref == &amp;#39;refs&#x2F;heads&#x2F;prod&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;uns-on&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;buntu-20.04&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;teps&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;heckout source code&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ctions&#x2F;checkout@v3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; change or remove according to your needs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;elete iOS icons&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;m -rf $WORKING_DIRECTORY&#x2F;AppIcons&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; change or remove according to your needs&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;reate export directory&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;kdir html5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; exports the game in html mode&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; more info here https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;godot-html-export&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; G&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;odot HTML5 export&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ulvui&#x2F;godot-html-export@v0.0.2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;orking-directory&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;WORKING_DIRECTORY&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; uploads to itch.io&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt;      #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#93A1A1, #586E75);font-style: italic;&quot;&gt; more info here https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;itchio-butler-upload&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; U&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;pload to itch.io&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ulvui&#x2F;itchio-butler-upload@v0.0.1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;        w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;orking-directory&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;tml5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;pi-key&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;{{ secrets.ITCHIO_API_KEY }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ser&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;imondalvai&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;all2box&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;          c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hannel&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;tml5&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;When the upload is finished, after a few seconds, you can already play the game in your browser.
Here you can see the uploaded games in the Channel history.&lt;br &#x2F;&gt;
&lt;img class=&quot;image&quot; src=&quot;html_channel.png&quot; alt=&quot;html channel history&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;And here the final result: Ball2Box playable in you browser on itch.io&lt;br &#x2F;&gt;
&lt;img class=&quot;image&quot; src=&quot;ball2box.png&quot; alt=&quot;Ball2Box on itch.io&quot;&gt;&lt;&#x2F;p&gt;
&lt;p&gt;You can find working examples in my games &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;pocket-broomball&#x2F;blob&#x2F;main&#x2F;.github&#x2F;workflows&#x2F;upload-itchio.yml&quot;&gt;Pocket Broomball&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;blob&#x2F;main&#x2F;.github&#x2F;workflows&#x2F;upload-itchio.yml&quot;&gt;Ball2Box&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;The single actions can also be used for other platforms or exports.
For example the html export can be uploaded to your website or another HTML games portal.
So can also the itch.io action be used to upload other games formats than HTML5 to itch.io like Android, iOS or Desktop.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>How to publish Godot 3 to F-Droid</title>
          <pubDate>Sat, 22 Apr 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-fdroid-publish/</link>
          <guid>https://simondalvai.org/blog/godot-fdroid-publish/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-fdroid-publish/">&lt;p&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;f-droid.org&quot;&gt;F-Droid&lt;&#x2F;a&gt; is an awesome app that gives you access to thousands of Free and Open Source Software apps and games.
It also respects your privacy, requires no login and lets you know if an app has anti-features like tracking, ads, proprietary assets or if it depends on the proprietary Google Play Services.
If an app has ads or tracks you, it is marked as &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;f-droid.org&#x2F;docs&#x2F;Anti-Features&quot;&gt;AntiFeatures&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
&lt;img class=&quot;image&quot; src=&quot;antifeatures.png&quot; alt=&quot;AntiFeatures example&quot;&gt;&lt;br &#x2F;&gt;
I was able to publish &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;ball2box&#x2F;&quot;&gt;Ball2Box&lt;&#x2F;a&gt; to F-Droid and here I will share the steps that are needed to do so.&lt;br &#x2F;&gt;
&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;f-droid.org&#x2F;en&#x2F;packages&#x2F;com.simondalvai.ball2box&#x2F;&quot;&gt;Here&lt;&#x2F;a&gt; you can find the published game.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;requirements&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#requirements&quot; aria-label=&quot;Anchor link for: requirements&quot;&gt;Requirements&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To publish a &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;godotengine.org&quot;&gt;Godot Engine&lt;&#x2F;a&gt; game to F-Droid you&#x27;ll need an Open Source game with the source code published on a &lt;strong&gt;public git repository&lt;&#x2F;strong&gt;.
You also need a Gitlab account to create a merge request to the F-Droid Data &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;fdroid&#x2F;fdroiddata&quot;&gt;repository&lt;&#x2F;a&gt; or you can make an Application Proposal where others include your app.&lt;br &#x2F;&gt;
In the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;f-droid.org&#x2F;docs&#x2F;Inclusion_How-To&#x2F;&quot;&gt;documentation&lt;&#x2F;a&gt; you can read how the inclusion works.
You also need a metadata &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;tree&#x2F;main&#x2F;metadata&quot;&gt;directory&lt;&#x2F;a&gt; in your repo with some screenshots, a description and the changelogs of your game.&lt;br &#x2F;&gt;
F-Droid builds its apps itself and &lt;strong&gt;all its dependencies&lt;&#x2F;strong&gt; completely from the source.
That means that you need also to build the Godot Engine from its source code.&lt;br &#x2F;&gt;
If you have other &lt;strong&gt;third party dependencies&lt;&#x2F;strong&gt; you have also to build them from the source code.
My game doesn&#x27;t have any other dependency than the Godot Engine, so if your game has some, you will have to extend the following build recipe with the steps to build your dependencies.&lt;br &#x2F;&gt;
All the steps needed are written in a yaml build recipe file.
The best is to follow the official F-Droid Developer &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;f-droid.org&#x2F;en&#x2F;docs&#x2F;&quot;&gt;documentation&lt;&#x2F;a&gt; so you will follow always the latest and correct steps.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;the-godot-build-recipe&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-godot-build-recipe&quot; aria-label=&quot;Anchor link for: the-godot-build-recipe&quot;&gt;The Godot build recipe&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here the Godot build recipe.
You can find the always up to date version on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;fdroid&#x2F;fdroiddata&#x2F;-&#x2F;blob&#x2F;master&#x2F;metadata&#x2F;com.simondalvai.ball2box.yml&quot;&gt;Gitlab&lt;&#x2F;a&gt;&lt;br &#x2F;&gt;
You&#x27;ll also need a &lt;strong&gt;metadata&lt;&#x2F;strong&gt; directory and a &lt;strong&gt;exports_preset.cfg&lt;&#x2F;strong&gt; in the repo of you game.
You can find mine on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&quot;&gt;Github&lt;&#x2F;a&gt; in the fdroid and metadata directories.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ategories&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; G&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ames&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;L&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;icense&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;GPL-3.0-or-later&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;uthorName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;imon Dalvai&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;uthorEmail&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;nfo@simondalvai.org&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;uthorWebSite&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ttps:&#x2F;&#x2F;simondalvai.org&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;W&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ebSite&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ttps:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;ball2box&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ourceCode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ttps:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;I&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ssueTracker&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ttps:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;issues&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;onate&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ttps:&#x2F;&#x2F;simondalvai.org&#x2F;donate&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;N&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;all2Box&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;utoName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;all2Box&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;epoType&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;it&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;epo&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; h&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ttps:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box.git&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;uilds&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ersionName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2.2.6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    v&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ersionCode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 44&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ommit&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;9ec9a5f025542c27196a0f5b3507a652e05e907&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;udo&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;pt-get update&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;pt-get install -y clang gettext pkg-config scons&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    o&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;utput&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ame&#x2F;Ball2Box.apk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;rclibs&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; G&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;odot@6fed1ffa313c6760fa88b368ae580378daaef0f0&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;rebuild&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;v fdroid&#x2F;export_presets.cfg game&#x2F;export_presets.cfg&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ed -i &amp;#39;s&#x2F;FDROID = false&#x2F;FDROID = true&#x2F;g&amp;#39; game&#x2F;src&#x2F;globals&#x2F;Global.gd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;uild&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;xport HOME=$PWD&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;p -R $$Godot$$ godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;eytool -genkey -v -keystore debug.keystore -storepass android -alias androiddebugkey&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;eypass android -dname &amp;quot;CN=Android Debug,O=Android,C=US&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;kdir -p .&#x2F;.config&#x2F;godot&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;xport SDK_PATH=&amp;quot;export&#x2F;android&#x2F;android_sdk_path = \&amp;quot;$$SDK$$\&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;xport DEBUG_KEYSTORE_PATH=&amp;quot;export&#x2F;android&#x2F;debug_keystore = \&amp;quot;$PWD&#x2F;debug.keystore\&amp;quot;&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cho &amp;#39;[gd_resource type=&amp;quot;EditorSettings&amp;quot; format=2]&amp;#39; &amp;gt;&amp;gt; .&#x2F;.config&#x2F;godot&#x2F;editor_settings-3.tres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cho &amp;quot;[resource]&amp;quot;  &amp;gt;&amp;gt; .&#x2F;.config&#x2F;godot&#x2F;editor_settings-3.tres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cho $SDK_PATH &amp;gt;&amp;gt; .&#x2F;.config&#x2F;godot&#x2F;editor_settings-3.tres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cho $DEBUG_KEYSTORE_PATH &amp;gt;&amp;gt; .&#x2F;.config&#x2F;godot&#x2F;editor_settings-3.tres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cho &amp;#39;export&#x2F;android&#x2F;debug_keystore_user = &amp;quot;androiddebugkey&amp;quot;&amp;#39; &amp;gt;&amp;gt; .&#x2F;.config&#x2F;godot&#x2F;editor_settings-3.tres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cho &amp;#39;export&#x2F;android&#x2F;debug_keystore_pass = &amp;quot;android&amp;quot;&amp;#39; &amp;gt;&amp;gt; .&#x2F;.config&#x2F;godot&#x2F;editor_settings-3.tres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;d godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cons -j `nproc` platform=server use_llvm=yes unix_global_settings_path=&amp;quot;..&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;rofile=fdroid&#x2F;godot-build-options.py&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;xport ANDROID_NDK_ROOT=$$NDK$$&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cons -j `nproc` use_llvm=yes p=android target=release  unix_global_settings_path=&amp;quot;..&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ndroid_arch=armv7 profile=fdroid&#x2F;godot-build-options.py&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cons -j `nproc` use_llvm=yes p=android target=release  unix_global_settings_path=&amp;quot;..&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ndroid_arch=arm64v8 profile=fdroid&#x2F;godot-build-options.py&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ushd platform&#x2F;android&#x2F;java&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;radle generateGodotTemplates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;opd&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;d ..&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; m&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;kdir -p .&#x2F;.local&#x2F;share&#x2F;godot&#x2F;templates&#x2F;3.5.1.stable&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cho &amp;quot;3.5.1.stable&amp;quot; &amp;gt;&amp;gt; .&#x2F;.local&#x2F;share&#x2F;godot&#x2F;templates&#x2F;3.5.1.stable&#x2F;version.txt&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;p godot&#x2F;bin&#x2F;android_release.apk .&#x2F;.local&#x2F;share&#x2F;godot&#x2F;templates&#x2F;3.5.1.stable&#x2F;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&#x2F;godot&#x2F;bin&#x2F;godot_server.* -v --path game --export Android Ball2Box.apk&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ind . -iname &amp;quot;*.apk&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;      -&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cho &amp;quot;build end&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;dk&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;23c&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;utoUpdateMode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; V&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ersion&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;U&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;pdateCheckMode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; T&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ags&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;U&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;pdateCheckData&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; f&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;droid&#x2F;export_presets.cfg|version&#x2F;code=(\d+)|.|version&#x2F;name=&amp;quot;([\d.]+)&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;urrentVersion&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 2.2.6&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;urrentVersionCode&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 44&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;</description>
      </item>
      <item>
          <title>Support my work</title>
          <pubDate>Sun, 26 Mar 2023 22:48:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/donate/</link>
          <guid>https://simondalvai.org/donate/</guid>
          <description xml:base="https://simondalvai.org/donate/">&lt;p&gt;You can support me by buying my games on&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;store.steampowered.com&#x2F;developer&#x2F;simon-dalvai&quot;&gt;Steam&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.itch.io&#x2F;&quot;&gt;itch.io&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Leaving a &lt;strong&gt;honest review&lt;&#x2F;strong&gt; also helps me a lot.&lt;&#x2F;p&gt;
&lt;p&gt;I also have an account on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;liberapay.com&#x2F;dulvui&quot;&gt;Liberapay&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;donations&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#donations&quot; aria-label=&quot;Anchor link for: donations&quot;&gt;Donations&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This are donations I got before deactivating most donation platforms.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Anonymous&lt;&#x2F;strong&gt; donated 1€ on 21.10.2024&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Baffo&lt;&#x2F;strong&gt; donated 10€ on 04.09.2024&lt;br &#x2F;&gt;
&lt;em&gt;&quot;Great games, keep it up!&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Anonymous&lt;&#x2F;strong&gt; is donating 5€ per year since 10.01.2024&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Paul&lt;&#x2F;strong&gt; donated 4€ on 31.05.2023&lt;br &#x2F;&gt;
&lt;em&gt;&quot;I just finished Ball2Box and I enjoyed it. Thanks for creating fun games that are free of ads and trackers. I will try the rest of the games :)&quot;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Anonymous&lt;&#x2F;strong&gt; donated 7.50€ on 16.05.2023&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Anonymous&lt;&#x2F;strong&gt; donated 2€ on 05.04.2023&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;Anonymous&lt;&#x2F;strong&gt; donated 3€ on 12.02.2023&lt;&#x2F;p&gt;
&lt;h1 id=&quot;thank-you-all&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#thank-you-all&quot; aria-label=&quot;Anchor link for: thank-you-all&quot;&gt;THANK YOU ALL!&lt;&#x2F;a&gt;&lt;&#x2F;h1&gt;
</description>
      </item>
      <item>
          <title>CSS only dark mode without JS</title>
          <pubDate>Sun, 19 Mar 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/css-only-darkmode/</link>
          <guid>https://simondalvai.org/blog/css-only-darkmode/</guid>
          <description xml:base="https://simondalvai.org/blog/css-only-darkmode/">&lt;p&gt;Last week I implemented dark mode on my website, without using any JS and only modern CSS media queries.&lt;br &#x2F;&gt;
It was pretty sure, that dark mode can only be implemented using JS, but a quick online search proved me wrong.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;lets-make-it-dark&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#lets-make-it-dark&quot; aria-label=&quot;Anchor link for: lets-make-it-dark&quot;&gt;Lets make it dark&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;This css one liner can define how your site looks on a device with dark mode set in the browser settings.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;media&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;prefers-color-scheme&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; dark&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or if your main style is dark mode, you can define how the light mode will look.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;css&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;@&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;media&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;prefers-color-scheme&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; light&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And with this little scss and media query you can set dynamically the background and font color of the whole body of your html.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;scss&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$background-color-light&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;FDF6E3&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$background-color-dark&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt; #&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CB4B16, #CB4B16);&quot;&gt;002b36&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$font-color-light&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; $background-color-dark&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$font-color-dark&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; $background-color-light&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;body&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    background-color&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; $background-color-light&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    color&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; $font-color-light&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;    @&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;media&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;span&gt;prefers-color-scheme&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; dark&lt;&#x2F;span&gt;&lt;span&gt;)&lt;&#x2F;span&gt;&lt;span&gt; {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        background-color&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; $background-color-dark&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt;        color&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span&gt; $font-color-dark&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    }&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Of course, you can&#x27;t switch between dark mode and light mode with a button (or at least I don&#x27;t know, how to do that) like you could do with JS.
But anyway I can&#x27;t remember the last time I used a button like that and websites should follow directly the system settings.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-to-test-it&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-to-test-it&quot; aria-label=&quot;Anchor link for: how-to-test-it&quot;&gt;How to test it&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;To test it, you can simply switch the color theme of your browser in the settings and voilà: the site changes automatically colors.&lt;br &#x2F;&gt;
For this website I used the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;ethanschoonover.com&#x2F;solarized&#x2F;&quot;&gt;solarized&lt;&#x2F;a&gt; theme.
It is my favorite theme and I use the solarized light theme everywhere I can.&lt;&#x2F;p&gt;
&lt;p&gt;So here, the internet proved me again, that a simple website can have a lot of cool features, without using JS at all.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Godot Engine vs libGDX</title>
          <pubDate>Sun, 26 Feb 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-vs-libgdx/</link>
          <guid>https://simondalvai.org/blog/godot-vs-libgdx/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-vs-libgdx/">&lt;p&gt;I create games since 2018 and here I want to share my experience with &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;libgdx.com&#x2F;&quot;&gt;libGDX&lt;&#x2F;a&gt; and &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;godotengine.org&#x2F;&quot;&gt;Godot&lt;&#x2F;a&gt;.
Both are open source and completely free to use with no revenue share or license prices, like other game development environments have.
In total, I currently released 3 games with libGDX and 2 with Godot for Android and iOS.&lt;br &#x2F;&gt;
I started in 2018 with libGDX because I knew how to code Java and liked the fact that everything is code and there&#x27;s no GUI editor where I have to click checkboxes and hoping to remember which one did what.
Then, around 2020 I tried to use Godot version 3 and I really loved how it worked.
So, since then I develop games only with Godot but still maintain my libGDX games and I&#x27;m working on releasing them all on iOS.&lt;br &#x2F;&gt;
&lt;strong&gt;Note:&lt;&#x2F;strong&gt; This is my own experience that I want to share with you but of course some things might be subjective and biased by my opinions.
So, the best advice I can give is to try all game development environments that you want and find the one that works for you.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;libgdx&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#libgdx&quot; aria-label=&quot;Anchor link for: libgdx&quot;&gt;libGDX&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;LibGDX is a simple but powerful Java library for cross-platform game development.
You can create 2D and 3D games for Windows, macOS, Linux, Android, iOS and HTML5.
You need to code everything in Java and there&#x27;s no Editor like you get with Godot.
So, you can use your favorite Java IDE like Eclipse, IntelliJ, Android Studio or whatever you prefer.
This makes libGDX really powerful because it lets you control and define every aspect of your game.
From loading the assets, to freeing the memory and positioning the button is done by you and by pure code.
No automatic memory management or graphical editor to make this tasks easier.
It is still active maintained but it hasn&#x27;t a big developer community like Godot.
Unity has probably the biggest mobile games development community.
Since you can add every other Java or Android library of your choice, it supports a lot of third party plugins.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;android&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#android&quot; aria-label=&quot;Anchor link for: android&quot;&gt;Android&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Java and Kotlin are the official programming languages for Android and so, libGDX works really well on Android.
The final App size is really small.
My games are less than 3 MB big and the performance is really great.
I haven&#x27;t stress tested the performance, but it seems much faster than Godot, especially on older devices.
You can build your games with gradle and also use automated CI&#x2F;CD tools to automate everything.
Here you can find my Github Action to export and upload your games to the Google Play Store&lt;br &#x2F;&gt;
https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;libgdx-ios-upload&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ios&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ios&quot; aria-label=&quot;Anchor link for: ios&quot;&gt;iOS&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;LibGdx also works on iOS using the &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;robovm&#x2F;robovm-gradle-plugin&quot;&gt;RoboVM&lt;&#x2F;a&gt; gradle plugin.
It translates the Java code into iOS machine code and so it can work on iPhones.
The performance is good but the app size increases drastically.
The 3 MB now raise to around 50 MB or more, but it is the price to pay to have libGDX on iOS devices.
I also created a Github Action to export and upload your games to the Apple App Store&lt;br &#x2F;&gt;
https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;libgdx-ios-upload&lt;&#x2F;p&gt;
&lt;h3 id=&quot;useful-tools&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#useful-tools&quot; aria-label=&quot;Anchor link for: useful-tools&quot;&gt;Useful tools&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;The most useful tool I found to create your UI elements is the libGDX Skin Composer&lt;br &#x2F;&gt;
https:&#x2F;&#x2F;libgdx.com&#x2F;wiki&#x2F;tools&#x2F;skin-composer&lt;br &#x2F;&gt;
This tool gives you a easy way to create your custom buttons, fonts, labels etc. with a GUI editor.
It seems that now this tool also has a Scene Composer, I haven&#x27;t tried it yet.
So you can even create your game&#x27;s GUI with this tool without having to code.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;godot&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#godot&quot; aria-label=&quot;Anchor link for: godot&quot;&gt;Godot&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Godot is a also cross-platform game engine that has only a single executable without any other dependencies.
You simply need to download the around 30 MB big executable and run it on your Linux, Windows or macOS machine.
Since the editor itself is created with Godot and Godot can be exported to Android, there is even a running editor for Android.
It is still buggy and in early stage but it works!
Godot is still young (initial release 2014) but it already has a big community and a lot of contributors.
One downside of Godot (at the time of writing this, early 2023) is that some plugins, that you can easily find for other game engines, like Firebase or AdMob, have no official release and are solely created by the Godot community.
So the plugin you use today, might not work tomorrow, until you fix it by yourself.
I tried Google AdMob and Firebase on Godot, but then removed them, because I no longer wanted to contribute to privacy invading and with Ads loaded games.
Thus, I removed all third party libraries and hope to make a few bucks only with &lt;a href=&quot;&#x2F;donate&quot;&gt;donations&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h3 id=&quot;android-1&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#android-1&quot; aria-label=&quot;Anchor link for: android-1&quot;&gt;Android&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Godot works well on Android and an empty game is about 8 MB big.
My games are between 30 and 50 MB big, but most of the memory comes from the assets.
And of course, I also created a Github Action for Godot to export and upload your game to the Google Play Store&lt;br &#x2F;&gt;
https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;godot-android-export&lt;&#x2F;p&gt;
&lt;h3 id=&quot;ios-1&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#ios-1&quot; aria-label=&quot;Anchor link for: ios-1&quot;&gt;iOS&lt;&#x2F;a&gt;&lt;&#x2F;h3&gt;
&lt;p&gt;Godot also works well with iOS, but you&#x27;ll need a macOS device to export, execute and upload the game to the App Store.
Or you simply use my Github Actions that does the uploading automatically for you, with no physical Mac device needed&lt;br &#x2F;&gt;
https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;godot-ios-upload&lt;&#x2F;p&gt;
&lt;h2 id=&quot;final-thoughts&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#final-thoughts&quot; aria-label=&quot;Anchor link for: final-thoughts&quot;&gt;Final thoughts&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;If you know Java well and you want to take completely control of your game, then libGDX is perfect for you.
But if you like fast development, creating your UI by mouse dragging and clicking, you should go for Godot.
Both are powerful tools to create games.
I must say that starting with libGDX taught me the basics of game programming, from loading and freeing the used assets to using the game loop for drawing them.
So, switching then to Godot allowed me to appreciate all the magical automated tasks that Godot does behind the scenes even more.
As a result, I can focus more on the actual game than needing to code each button position manually.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>99Managers Futsal Edition</title>
          <pubDate>Wed, 15 Feb 2023 13:48:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/games/99managers-futsal-edition/</link>
          <guid>https://simondalvai.org/games/99managers-futsal-edition/</guid>
          <description xml:base="https://simondalvai.org/games/99managers-futsal-edition/">&lt;p&gt;99Managers™ Futsal Edition, is a Open Source Futsal Manager game.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;More info on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;99managers.org&quot;&gt;99managers.org&lt;&#x2F;a&gt;&lt;&#x2F;strong&gt;&lt;&#x2F;p&gt;
&lt;img class=&quot;image-wide&quot; alt=&quot;Screenshot of the game&quot; src=&quot;&#x2F;img&#x2F;game-icons&#x2F;99managers-futsal-capsule.webp&quot; &#x2F;&gt;
</description>
      </item>
      <item>
          <title>Godot - Automated screenshots</title>
          <pubDate>Sun, 22 Jan 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-automated-screenshots/</link>
          <guid>https://simondalvai.org/blog/godot-automated-screenshots/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-automated-screenshots/">&lt;p&gt;To publish a game to Apple App Store or Google Play Store, screenshots of the game are needed.
For Android you need screenshots of mobile devices and tablets and for iOS you need a screenshot of each currently supported device.&lt;br &#x2F;&gt;
With a little coding this boring and repetitive task can be automated.
Of course, it depends a lot on the type of game and its mechanics, if its even possible to automate this task.
But if it&#x27;s a simple game like &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;games&#x2F;ball2box&#x2F;&quot;&gt;Ball2Box&lt;&#x2F;a&gt; it will be easy.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-does-it-work&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-does-it-work&quot; aria-label=&quot;Anchor link for: how-does-it-work&quot;&gt;How does it work&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;First, the resolutions of the devices are defined.
The iPad screenshots can be reused as 7 inch and 10 inch tablet screenshots for Android.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const resolutions = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 &amp;quot;Android&amp;quot; :Vector2(1080,1920),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 &amp;quot;iPhone5.5&amp;quot; :Vector2(1242, 2208),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 &amp;quot;iPhone6.5&amp;quot; :Vector2(1284, 2778),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 &amp;quot;iPhone6.7&amp;quot;: Vector2(1290, 2796),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 &amp;quot;iPad12.9&amp;quot; : Vector2(2048, 2732)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then the paths of the scenes, that should be used for the screenshots, are defined.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const scenes = [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level1.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level10.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level11.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level13.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level24.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level70.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level99.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level105.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The following function changes the scene to the ones we defined in the last step and hides the menu.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _change_scene(scene_path):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	if scene != null:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		remove_child(scene)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		scene.queue_free()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	var next_scene = load(scene_path)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	scene = next_scene.instance()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	add_child(scene)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	# hide menu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	scene.get_node(&amp;quot;UI&#x2F;Menu&amp;quot;).hide()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;With the following OS function call, we can change the resolution of the screen while the game is executed.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;OS.set_window_size(resolutions.get(resolution))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then we get the texture data of the whole screen with the get_texture() Viewport function call.
Since the image would be upside down, we flip it first and then we can save it on the file system.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var image = get_viewport().get_texture().get_data().get_rect(fullscreen)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;image.flip_y()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;image.save_png(&amp;quot;..&#x2F;screenshots&#x2F;&amp;quot; + resolution + &amp;quot;-&amp;quot; + str(scene_counter) + &amp;quot;.png&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;h2 id=&quot;the-whole-code&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#the-whole-code&quot; aria-label=&quot;Anchor link for: the-whole-code&quot;&gt;The whole code&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Here, the whole code that iterates over the resolutions and scenes and takes the screenshots.
It can be executed with the &quot;Play custom scene&quot; button on the right top corner of the Godot editor.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;extends Spatial&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const resolutions = {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 &amp;quot;Android&amp;quot; :Vector2(1080,1920),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 &amp;quot;iPhone5.5&amp;quot; :Vector2(1242, 2208),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 &amp;quot;iPhone6.5&amp;quot; :Vector2(1284, 2778),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 &amp;quot;iPhone6.7&amp;quot;: Vector2(1290, 2796),&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	 &amp;quot;iPad12.9&amp;quot; : Vector2(2048, 2732)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;const scenes = [&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level1.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level10.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level11.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level13.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level24.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level70.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level99.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&amp;quot;res:&#x2F;&#x2F;src&#x2F;levels&#x2F;Level105.tscn&amp;quot;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;var scene&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _ready():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	var scene_counter = 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	for scene in scenes:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		_change_scene(scene)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		for resolution in resolutions.keys():&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			OS.set_window_size(resolutions.get(resolution))&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			yield(get_tree().create_timer(2), &amp;quot;timeout&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			# calculate x&#x2F;y offset for bigger screens like iPads to center the screenshot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			var x = (resolutions.get(resolution).x - get_viewport().get_texture().get_size().x) &#x2F; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			var y = (resolutions.get(resolution).y - get_viewport().get_texture().get_size().y) &#x2F; 2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			var fullscreen = Rect2(0 - x, 0 - y, resolutions.get(resolution).x, resolutions.get(resolution).y)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			var image = get_viewport().get_texture().get_data().get_rect(fullscreen)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			image.flip_y()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;			image.save_png(&amp;quot;..&#x2F;screenshots&#x2F;&amp;quot; + resolution + &amp;quot;-&amp;quot; + str(scene_counter) + &amp;quot;.png&amp;quot;)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		scene_counter += 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	get_tree().quit()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;func _change_scene(scene_path):&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	if scene != null:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		remove_child(scene)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;		scene.queue_free()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	var next_scene = load(scene_path)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	scene = next_scene.instance()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	add_child(scene)&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	# hide menu&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;	scene.get_node(&amp;quot;UI&#x2F;Menu&amp;quot;).hide()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This script could be used to create a tool for the Godot Asset Store, so it could be simply installed from there, but for my use case this is enough for now.&lt;br &#x2F;&gt;
You can find this code and the whole game also on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;blob&#x2F;main&#x2F;game&#x2F;src&#x2F;screenshot-taker&#x2F;ScreenshotTaker.gd&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Automated Godot Android upload with Github Actions</title>
          <pubDate>Sun, 15 Jan 2023 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-android-upload/</link>
          <guid>https://simondalvai.org/blog/godot-android-upload/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-android-upload/">&lt;p&gt;In my last blog &lt;a href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;godot-ios-upload&#x2F;&quot;&gt;post&lt;&#x2F;a&gt; I explained how my Github Action, to automatically export and upload Godot iOS games to the Apple App Store, works.
I created the same action for Android and the Google Play Store and in this post I will explain how it works.
I&#x27;m using also this action already in my Godot games, like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;pocket-broomball&#x2F;blob&#x2F;main&#x2F;.github&#x2F;workflows&#x2F;upload-android.yml&quot;&gt;PocketBroomball&lt;&#x2F;a&gt; or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;blob&#x2F;main&#x2F;.github&#x2F;workflows&#x2F;upload-android.yml&quot;&gt;Ball2Box&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
You can find the repo of the action on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;godot-android-export&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-does-this-action-work&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-does-this-action-work&quot; aria-label=&quot;Anchor link for: how-does-this-action-work&quot;&gt;How does this action work?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The first step is setting up Java for the Github runner with the &lt;code&gt;actions&#x2F;setup-java@v3&lt;&#x2F;code&gt; action. This downloads everything needed and sets the environment variables like JAVA_HOME etc.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;et up JDK 1.8&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ctions&#x2F;setup-java@v3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    d&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;istribution&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;temurin&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    j&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ava-version&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#D33682, #D33682);&quot;&gt; 11&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Android SDK and its tools are another must have and for that we run the &lt;code&gt;android-actions&#x2F;setup-android@v2&lt;&#x2F;code&gt; action.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;etup Android SDK&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ndroid-actions&#x2F;setup-android@v2&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then a cache is created using the &lt;code&gt;actions&#x2F;cache@v3&lt;&#x2F;code&gt; action. This cache saves the Godot Engine executable, configurations and export templates in a persistent memory, in order to save time and Github&#x27;s bandwidth. A new cache is created if the &lt;code&gt;godot-version&lt;&#x2F;code&gt; of the inputs changes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ache Godot files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ache-godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ctions&#x2F;cache@v3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        ~&#x2F;.local&#x2F;share&#x2F;godot&#x2F;**&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        &#x2F;usr&#x2F;local&#x2F;bin&#x2F;godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        ~&#x2F;.config&#x2F;godot&#x2F;**&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ey&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;{{ runner.os }}-godot-${{ inputs.godot-version }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now the headless Godot executables get downloaded but only if the cache, created the step before, doesn&#x27;t get a hit.
The needed export templates get downloaded and extracted too.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ownload and config Godot Engine headless linux server and templates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;teps.cache-godot.outputs.cache-hit != &amp;#39;true&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    wget -q https:&#x2F;&#x2F;downloads.tuxfamily.org&#x2F;godotengine&#x2F;${{ inputs.godot-version }}&#x2F;Godot_v${{ inputs.godot-version }}-stable_linux_headless.64.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    wget -q https:&#x2F;&#x2F;downloads.tuxfamily.org&#x2F;godotengine&#x2F;${{ inputs.godot-version }}&#x2F;Godot_v${{ inputs.godot-version }}-stable_export_templates.tpz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    mkdir ~&#x2F;.cache&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    mkdir -p ~&#x2F;.config&#x2F;godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    mkdir -p ~&#x2F;.local&#x2F;share&#x2F;godot&#x2F;templates&#x2F;${{ inputs.godot-version }}.stable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    unzip Godot_v${{ inputs.godot-version }}-stable_linux_headless.64.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    mv Godot_v${{ inputs.godot-version }}-stable_linux_headless.64 &#x2F;usr&#x2F;local&#x2F;bin&#x2F;godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    unzip Godot_v${{ inputs.godot-version }}-stable_export_templates.tpz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    mv templates&#x2F;* ~&#x2F;.local&#x2F;share&#x2F;godot&#x2F;templates&#x2F;${{ inputs.godot-version }}.stable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    rm -f Godot_v${{ inputs.godot-version }}-stable_linux_headless.64.zip Godot_v${{ inputs.godot-version }}-stable_export_templates.tpz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    godot -e -q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now the path for the Android SDK can be defined in the Godot Editor settings, so that the engine knows, where to find the SDK and build tools.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;et Android SDK path in Godot Editor settings&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;teps.cache-godot.outputs.cache-hit != &amp;#39;true&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    S&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ETTINGS&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        export&#x2F;android&#x2F;android_sdk_path = &amp;quot;&#x2F;usr&#x2F;local&#x2F;lib&#x2F;android&#x2F;sdk&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        export&#x2F;android&#x2F;shutdown_adb_on_exit = true&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        export&#x2F;android&#x2F;force_system_user = false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cho $SETTINGS &amp;gt;&amp;gt; ~&#x2F;.config&#x2F;godot&#x2F;editor_settings-3.tres&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The setup of Java, Android and Godot is now complete and we can actually export the game with this simple one liner.
Godot is quite cool, isn&#x27;t it?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;xport&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; g&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;odot --path ${{ inputs.working-directory }} --export Android&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And now we can run the final step by uploading the exported game to the Google Play Store using the &lt;code&gt;uses: r0adkll&#x2F;upload-google-play@v1&lt;&#x2F;code&gt; action.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ublish to Play Store&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;0adkll&#x2F;upload-google-play@v1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;erviceAccountJson&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;{{ inputs.service-account-json }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ackageName&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;{{ inputs.package-name }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;eleaseFiles&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;{{ inputs.release-file }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    t&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;rack&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;{{ inputs.release-track }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;tatus&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ompleted&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The Android action is quite simpler than the iOS action and also easier to maintain because you don&#x27;t have to care about yearly expiring Developer Certificates and Provisioning Profiles. Probably it is because I&#x27;m simply too unexperienced with iOS development and thus it is a pain every time I need to renew everything. But automating, at least the export and upload, is a big help, especially as a solo developer. It saves me a lot of time and brings much more joy when you can upload everything with a simple &lt;code&gt;git push&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;You can find the complete action and instructions on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;godot-android-export&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
If you have problems or need help with the action, simply open an issue in the repository.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Automated Godot 3.x iOS upload with Github Actions</title>
          <pubDate>Thu, 29 Dec 2022 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/blog/godot-ios-upload/</link>
          <guid>https://simondalvai.org/blog/godot-ios-upload/</guid>
          <description xml:base="https://simondalvai.org/blog/godot-ios-upload/">&lt;p&gt;Github Actions allow you to automate repetitive tasks, like exporting your game for iOS and uploading it to the App Store.
It also brings the advantage that you don&#x27;t need a Mac at all. So it saves you time and money, if you&#x27;re not a Mac user.&lt;br &#x2F;&gt;
I&#x27;m using the action already in my Godot games like &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;pocket-broomball&#x2F;blob&#x2F;main&#x2F;.github&#x2F;workflows&#x2F;upload-ios.yml&quot;&gt;Pocket Broomball&lt;&#x2F;a&gt; or &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;ball2box&#x2F;blob&#x2F;main&#x2F;.github&#x2F;workflows&#x2F;upload-ios.yml&quot;&gt;Ball2Box&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Note: The action steps and versions change over time.
Find the latest version of the action &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;godot-ios-upload&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;github-actions-pricing&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#github-actions-pricing&quot; aria-label=&quot;Anchor link for: github-actions-pricing&quot;&gt;Github Actions pricing&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;Github Actions are always free only for Open Source repositories.
On private you get 2000 to 3000 run minutes per month, depending on the type of your account.
Additionally, MacOS actions consume 10x times the minutes of a Linux machine, so you actually get 200 to 300 minutes per month.&lt;&#x2F;p&gt;
&lt;p&gt;Here the detailed documentation about pricing https:&#x2F;&#x2F;docs.github.com&#x2F;en&#x2F;billing&#x2F;managing-billing-for-github-actions&#x2F;about-billing-for-github-actions&lt;&#x2F;p&gt;
&lt;h2 id=&quot;how-does-the-action-work&quot;&gt;&lt;a class=&quot;zola-anchor&quot; href=&quot;#how-does-the-action-work&quot; aria-label=&quot;Anchor link for: how-does-the-action-work&quot;&gt;How does the action work?&lt;&#x2F;a&gt;&lt;&#x2F;h2&gt;
&lt;p&gt;The action uses only macOS built-in command line tools like &lt;code&gt;xcodebuild&lt;&#x2F;code&gt; and &lt;code&gt;xcrun&lt;&#x2F;code&gt; and has no third party dependencies.
So you can be sure that it always works with the tools Apple itself provides.&lt;&#x2F;p&gt;
&lt;p&gt;First, a check is made to see if the action actually runs on a macOS runner, because it wouldn&#x27;t work on a Linux or Windows runner.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;heck is running on mac-os&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;unner.os != &amp;#39;macos&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;xit 1&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then a cache is created using the &lt;code&gt;actions&#x2F;cache@v3&lt;&#x2F;code&gt; action. This cache saves the Godot Engine executable, configurations and export templates in a persistent memory, in order to save time and Github&#x27;s bandwidth. A new cache is created if the &lt;code&gt;godot-version&lt;&#x2F;code&gt; of the inputs changes.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; C&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ache Godot files&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;d&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; c&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ache-godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    u&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ses&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; a&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ctions&#x2F;cache@v3&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    w&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ith&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    p&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ath&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        ~&#x2F;.local&#x2F;share&#x2F;godot&#x2F;**&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        ~&#x2F;.config&#x2F;godot&#x2F;**&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    k&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ey&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;{{ runner.os }}-godot-${{ inputs.godot-version }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The action uses a headless macOS build that you can find on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;huskeee&#x2F;godot-headless-mac&quot;&gt;Github&lt;&#x2F;a&gt;.
This build allows the action to run Godot without UI and exporting the game for iOS. So, here the headless build together with the export templates is downloaded, but if there is a cache hit, the files from the cache you created before are used.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; D&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ownload and config Godot Engine headless linux server and templates&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;teps.cache-godot.outputs.cache-hit != &amp;#39;true&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    wget -q https:&#x2F;&#x2F;github.com&#x2F;huskeee&#x2F;godot-headless-mac&#x2F;releases&#x2F;download&#x2F;${{ inputs.godot-version }}-stable&#x2F;Godot_v${{ inputs.godot-version }}-stable_mac_headless.64.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    wget -q https:&#x2F;&#x2F;downloads.tuxfamily.org&#x2F;godotengine&#x2F;${{ inputs.godot-version }}&#x2F;Godot_v${{ inputs.godot-version }}-stable_export_templates.tpz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    unzip Godot_v${{ inputs.godot-version }}-stable_export_templates.tpz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    unzip Godot_v${{ inputs.godot-version }}-stable_mac_headless.64.zip&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    mkdir -p ~&#x2F;.config&#x2F;godot&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    mkdir -p ~&#x2F;.local&#x2F;share&#x2F;godot&#x2F;templates&#x2F;${{ inputs.godot-version }}.stable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    mv templates&#x2F;* ~&#x2F;.local&#x2F;share&#x2F;godot&#x2F;templates&#x2F;${{ inputs.godot-version }}.stable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    mv bin&#x2F;godot .&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    .&#x2F;godot -e -q&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    rm -f Godot_v${{ inputs.godot-version }}-stable_linux_headless.64.zip Godot_v${{ inputs.godot-version }}-stable_export_templates.tpz&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now the game gets exported for iOS with this simple one liner. The exported files will be located in &lt;code&gt;$PWD&#x2F;build&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; G&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;odot iOS export&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; .&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;&#x2F;godot --path ${{ inputs.working-directory }} --export iOS&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;For the signing of the iOS export we need the UUID of the provisioning profile. With this command, the UUID gets extracted and saved as PP_UUID in the Github Actions environment.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;xtract Provisioning profile UUID and create PP_UUID env variable&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;cho &amp;quot;PP_UUID=$(grep -a -A 1 &amp;#39;UUID&amp;#39; ${{ inputs.provision-profile-path }} | grep string | sed -e &amp;quot;s|&amp;lt;string&amp;gt;||&amp;quot; -e &amp;quot;s|&amp;lt;&#x2F;string&amp;gt;||&amp;quot; | tr -d &amp;#39;\t&amp;#39;)&amp;quot; &amp;gt;&amp;gt; $GITHUB_ENV&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To make sure the runner uses the correct XCode version, you force it to use a version that works well with the Godot Engine.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; F&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;orce XCode 13.4&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;udo xcode-select -switch &#x2F;Applications&#x2F;Xcode_13.4.app&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now you use the &lt;code&gt;xcodebuild&lt;&#x2F;code&gt; to make the iOS export ready for the upload.
If external dependencies are used with the following command, the action makes sure that they are configured correctly.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; R&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;esolve package dependencies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;codebuild -resolvePackageDependencies&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;An archive of the export is needed before we can create the .ipa file that can be uploaded. In this step, also the signing with the Developer Certificate and Provisioning Profile takes place.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; B&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;uild the xarchive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    set -eo pipefail&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    xcodebuild  clean archive \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -scheme ${{ inputs.project-name }} \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -configuration &amp;quot;Release&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -sdk iphoneos \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -archivePath &amp;quot;$PWD&#x2F;build&#x2F;${{ inputs.project-name }}.xcarchive&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -destination &amp;quot;generic&#x2F;platform=iOS,name=Any iOS Device&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        OTHER_CODE_SIGN_FLAGS=&amp;quot;--keychain $RUNNER_TEMP&#x2F;app-signing.keychain-db&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        CODE_SIGN_STYLE=Manual \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        PROVISIONING_PROFILE=$PP_UUID \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        CODE_SIGN_IDENTITY=&amp;quot;Apple Distribution&amp;quot;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then you can export the archive of the latest step to a single .ipa file that is ready for the upload.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; E&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;xport .ipa&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    set -eo pipefail&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    xcodebuild -archivePath &amp;quot;$PWD&#x2F;build&#x2F;${{ inputs.project-name }}.xcarchive&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -exportOptionsPlist exportOptions.plist \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -exportPath $PWD&#x2F;build \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -allowProvisioningUpdates \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -exportArchive&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The final step uploads the .ipa file to the App Store using the &lt;code&gt;xcrun&lt;&#x2F;code&gt; tool.
An Apple user account with upload permission is needed and I recommend using a separate service account instead of the admin account.&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#657B83, #839496); background-color: light-dark(#FDF6E3, #002B36);&quot;&gt;&lt;code data-lang=&quot;yaml&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;-&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt; n&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;ame&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; P&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ublish the App on TestFlight&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;hell&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; b&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;ash&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    i&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;f&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; s&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;uccess()&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    e&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;nv&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;PPLEID_USERNAME&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;{{ inputs.apple-id-username }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    A&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;PPLEID_PASSWORD&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt; $&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;{{ inputs.apple-id-password }}&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;    r&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#268BD2, #268BD2);&quot;&gt;un&lt;&#x2F;span&gt;&lt;span&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#859900, #859900);&quot;&gt; |&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;    xcrun altool \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        --upload-app \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -t ios \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -f $PWD&#x2F;build&#x2F;*.ipa \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -u &amp;quot;${{ inputs.apple-id-username }}&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        -p &amp;quot;${{ inputs.apple-id-password }}&amp;quot; \&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#2AA198, #2AA198);&quot;&gt;        --verbose&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can find the complete action on &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;dulvui&#x2F;godot-ios-upload&#x2F;blob&#x2F;main&#x2F;action.yml&quot;&gt;Github&lt;&#x2F;a&gt;.&lt;br &#x2F;&gt;
If you have problems or need help with the action, simply open an issue in the repository.&lt;&#x2F;p&gt;
&lt;p&gt;Read &lt;a rel=&quot;noopener external&quot; target=&quot;_blank&quot; href=&quot;https:&#x2F;&#x2F;simondalvai.org&#x2F;blog&#x2F;dev-cert-linux&quot;&gt;here&lt;&#x2F;a&gt; on how to create a Apple Developer Certificate on Linux without a Mac.&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Ball2Box</title>
          <pubDate>Thu, 29 Sep 2022 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/games/ball2box/</link>
          <guid>https://simondalvai.org/games/ball2box/</guid>
          <description xml:base="https://simondalvai.org/games/ball2box/">&lt;p&gt;Swipe to shoot the ball into the box in &lt;b&gt;over 100 levels&lt;&#x2F;b&gt; with only one finger.
Can you get all three stars on all levels?&lt;&#x2F;p&gt;
&lt;p&gt;🕹️ 100+ levels and more coming soon...&lt;br &#x2F;&gt;
🌈 20+ different styled balls to collect&lt;br &#x2F;&gt;
📡 Offline game&lt;br &#x2F;&gt;
📺 No ads&lt;br &#x2F;&gt;
💸 No In-App purchases&lt;br &#x2F;&gt;
🕵️‍♀️ No user tracking&lt;br &#x2F;&gt;
🛑 No permissions&lt;br &#x2F;&gt;
👨‍💻 Created with Godot Engine 3&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Pocket Broomball</title>
          <pubDate>Wed, 29 Sep 2021 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/games/pocket-broomball/</link>
          <guid>https://simondalvai.org/games/pocket-broomball/</guid>
          <description xml:base="https://simondalvai.org/games/pocket-broomball/">&lt;p&gt;The coolest winter sport has finally come to your phone!&lt;&#x2F;p&gt;
&lt;p&gt;&lt;b&gt;Win the Championship&lt;&#x2F;b&gt; and unlock all the &lt;b&gt;100+ real world teams&lt;&#x2F;b&gt; of the following leagues:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;North American Broomball League&lt;&#x2F;li&gt;
&lt;li&gt;Maritime Broomball Association&lt;&#x2F;li&gt;
&lt;li&gt;Penrith Broombal competition&lt;&#x2F;li&gt;
&lt;li&gt;Ontario League&lt;&#x2F;li&gt;
&lt;li&gt;Italian Broomball League&lt;&#x2F;li&gt;
&lt;li&gt;Swiss Broomball Association A + B&lt;&#x2F;li&gt;
&lt;li&gt;International Women League&lt;&#x2F;li&gt;
&lt;li&gt;International League&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;If you want to add &lt;b&gt;your team&lt;&#x2F;b&gt; to the game, send me a mail at &lt;a href=&quot;mailto:info@simondalvai.org?subject=Pocket Broomball: new team&quot;&gt;info@simondalvai.org&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;p&gt;🧹 100+ real-world teams&lt;br &#x2F;&gt;
🌈 20+ different styled balls to collect&lt;br &#x2F;&gt;
📡 Offline game&lt;br &#x2F;&gt;
📺 No ads&lt;br &#x2F;&gt;
💸 No In-App purchases&lt;br &#x2F;&gt;
🕵️‍♀️ No user tracking&lt;br &#x2F;&gt;
🛑 No permissions&lt;br &#x2F;&gt;
👨‍💻 Created with Godot Engine 3&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Sn4ke</title>
          <pubDate>Tue, 29 Sep 2020 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/games/sn4ke/</link>
          <guid>https://simondalvai.org/games/sn4ke/</guid>
          <description xml:base="https://simondalvai.org/games/sn4ke/">&lt;p&gt;Play the old school classic Snake with pixel retro look, modern swipe controls and 60 unique Levels!&lt;br &#x2F;&gt;
What will be your high score?&lt;&#x2F;p&gt;
&lt;p&gt;🕹️ 60 levels&lt;br &#x2F;&gt;
🌈 4 different color themes&lt;br &#x2F;&gt;
💾 Only 3MB on Android&lt;br &#x2F;&gt;
📡 Offline game&lt;br &#x2F;&gt;
📺 No ads&lt;br &#x2F;&gt;
💸 No In-App purchases&lt;br &#x2F;&gt;
🕵️‍♀️ No user tracking&lt;br &#x2F;&gt;
🛑 No permissions&lt;br &#x2F;&gt;
👨‍💻 Created with libGDX&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>WhatColor</title>
          <pubDate>Tue, 29 Oct 2019 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/games/whatcolor/</link>
          <guid>https://simondalvai.org/games/whatcolor/</guid>
          <description xml:base="https://simondalvai.org/games/whatcolor/">&lt;p&gt;&lt;b&gt;Remember&lt;&#x2F;b&gt; the pattern you&#x27;ll see, because one color will &lt;b&gt;disappear&lt;&#x2F;b&gt;!
&lt;b&gt;Click&lt;&#x2F;b&gt; the missing color on the buttons under the pattern.&lt;br &#x2F;&gt;
This game is pure memory training for your &lt;b&gt;brain&lt;&#x2F;b&gt; 🧠&lt;&#x2F;p&gt;
&lt;p&gt;Train your &lt;b&gt;eye-hand coordination&lt;&#x2F;b&gt; by searching for the missing color!
But be fast, because the time is running out ⌛&lt;br &#x2F;&gt;
Every correct color gives you 2 more seconds for the next one.&lt;br &#x2F;&gt;
It might seem easy at the beginning, but it&#x27;s hard to stay &lt;b&gt;focused&lt;&#x2F;b&gt; and &lt;b&gt;concentrated&lt;&#x2F;b&gt;!
So improve your &lt;b&gt;concentration&lt;&#x2F;b&gt; by playing this memory training game!&lt;br &#x2F;&gt;
Play every day and see how your &lt;b&gt;memory&lt;&#x2F;b&gt; and &lt;b&gt;focus&lt;&#x2F;b&gt; gets faster and better!&lt;&#x2F;p&gt;
&lt;p&gt;🌈 60 patterns&lt;br &#x2F;&gt;
💾 Only 3MB&lt;br &#x2F;&gt;
📡 Offline game&lt;br &#x2F;&gt;
📺 No ads&lt;br &#x2F;&gt;
💸 No In-App purchases&lt;br &#x2F;&gt;
🕵️‍♀️ No user tracking&lt;br &#x2F;&gt;
🛑 No permissions&lt;br &#x2F;&gt;
👨‍💻 Created with libGDX&lt;&#x2F;p&gt;
</description>
      </item>
      <item>
          <title>Color Shooter</title>
          <pubDate>Sun, 29 Sep 2019 00:00:00 +0000</pubDate>
          <author>Simon Dalvai</author>
          <link>https://simondalvai.org/games/color-shooter/</link>
          <guid>https://simondalvai.org/games/color-shooter/</guid>
          <description xml:base="https://simondalvai.org/games/color-shooter/">&lt;p&gt;My first developed game, so don&#x27;t expect much.&lt;&#x2F;p&gt;
&lt;p&gt;Shoot green, yellow, red and blue by tapping the screen and let white reach the centre.&lt;&#x2F;p&gt;
&lt;p&gt;For every white that reaches the centre, you get one point.
The higher your score, the faster the speed!&lt;&#x2F;p&gt;
</description>
      </item>
    </channel>
</rss>
